mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #12211 from overleaf/em-camel-case-real-time
Camel case variables in real-time GitOrigin-RevId: 0a35d2e39d54c258bed017ea4dcdbf9a19a2a9b1
This commit is contained in:
parent
5ae698ec6c
commit
d9e0215aee
35 changed files with 528 additions and 587 deletions
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
const { NotAuthorizedError } = require('./Errors')
|
const { NotAuthorizedError } = require('./Errors')
|
||||||
|
|
||||||
let AuthorizationManager
|
let AuthorizationManager
|
||||||
|
@ -29,39 +26,39 @@ module.exports = AuthorizationManager = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
assertClientCanViewProjectAndDoc(client, doc_id, callback) {
|
assertClientCanViewProjectAndDoc(client, docId, callback) {
|
||||||
AuthorizationManager.assertClientCanViewProject(client, function (error) {
|
AuthorizationManager.assertClientCanViewProject(client, function (error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
return callback(error)
|
return callback(error)
|
||||||
}
|
}
|
||||||
AuthorizationManager._assertClientCanAccessDoc(client, doc_id, callback)
|
AuthorizationManager._assertClientCanAccessDoc(client, docId, callback)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
assertClientCanEditProjectAndDoc(client, doc_id, callback) {
|
assertClientCanEditProjectAndDoc(client, docId, callback) {
|
||||||
AuthorizationManager.assertClientCanEditProject(client, function (error) {
|
AuthorizationManager.assertClientCanEditProject(client, function (error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
return callback(error)
|
return callback(error)
|
||||||
}
|
}
|
||||||
AuthorizationManager._assertClientCanAccessDoc(client, doc_id, callback)
|
AuthorizationManager._assertClientCanAccessDoc(client, docId, callback)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
_assertClientCanAccessDoc(client, doc_id, callback) {
|
_assertClientCanAccessDoc(client, docId, callback) {
|
||||||
if (client.ol_context[`doc:${doc_id}`] === 'allowed') {
|
if (client.ol_context[`doc:${docId}`] === 'allowed') {
|
||||||
callback(null)
|
callback(null)
|
||||||
} else {
|
} else {
|
||||||
callback(new NotAuthorizedError())
|
callback(new NotAuthorizedError())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
addAccessToDoc(client, doc_id, callback) {
|
addAccessToDoc(client, docId, callback) {
|
||||||
client.ol_context[`doc:${doc_id}`] = 'allowed'
|
client.ol_context[`doc:${docId}`] = 'allowed'
|
||||||
callback(null)
|
callback(null)
|
||||||
},
|
},
|
||||||
|
|
||||||
removeAccessToDoc(client, doc_id, callback) {
|
removeAccessToDoc(client, docId, callback) {
|
||||||
delete client.ol_context[`doc:${doc_id}`]
|
delete client.ol_context[`doc:${docId}`]
|
||||||
callback(null)
|
callback(null)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
const async = require('async')
|
const async = require('async')
|
||||||
const Settings = require('@overleaf/settings')
|
const Settings = require('@overleaf/settings')
|
||||||
const logger = require('@overleaf/logger')
|
const logger = require('@overleaf/logger')
|
||||||
|
@ -20,52 +17,52 @@ module.exports = {
|
||||||
// Use the same method for when a user connects, and when a user sends a cursor
|
// Use the same method for when a user connects, and when a user sends a cursor
|
||||||
// update. This way we don't care if the connected_user key has expired when
|
// update. This way we don't care if the connected_user key has expired when
|
||||||
// we receive a cursor update.
|
// we receive a cursor update.
|
||||||
updateUserPosition(project_id, client_id, user, cursorData, callback) {
|
updateUserPosition(projectId, clientId, user, cursorData, callback) {
|
||||||
logger.debug(
|
logger.debug({ projectId, clientId }, 'marking user as joined or connected')
|
||||||
{ project_id, client_id },
|
|
||||||
'marking user as joined or connected'
|
|
||||||
)
|
|
||||||
|
|
||||||
const multi = rclient.multi()
|
const multi = rclient.multi()
|
||||||
|
|
||||||
multi.sadd(Keys.clientsInProject({ project_id }), client_id)
|
multi.sadd(Keys.clientsInProject({ project_id: projectId }), clientId)
|
||||||
multi.expire(Keys.clientsInProject({ project_id }), FOUR_DAYS_IN_S)
|
multi.expire(
|
||||||
|
Keys.clientsInProject({ project_id: projectId }),
|
||||||
|
FOUR_DAYS_IN_S
|
||||||
|
)
|
||||||
|
|
||||||
multi.hset(
|
multi.hset(
|
||||||
Keys.connectedUser({ project_id, client_id }),
|
Keys.connectedUser({ project_id: projectId, client_id: clientId }),
|
||||||
'last_updated_at',
|
'last_updated_at',
|
||||||
Date.now()
|
Date.now()
|
||||||
)
|
)
|
||||||
multi.hset(
|
multi.hset(
|
||||||
Keys.connectedUser({ project_id, client_id }),
|
Keys.connectedUser({ project_id: projectId, client_id: clientId }),
|
||||||
'user_id',
|
'user_id',
|
||||||
user._id
|
user._id
|
||||||
)
|
)
|
||||||
multi.hset(
|
multi.hset(
|
||||||
Keys.connectedUser({ project_id, client_id }),
|
Keys.connectedUser({ project_id: projectId, client_id: clientId }),
|
||||||
'first_name',
|
'first_name',
|
||||||
user.first_name || ''
|
user.first_name || ''
|
||||||
)
|
)
|
||||||
multi.hset(
|
multi.hset(
|
||||||
Keys.connectedUser({ project_id, client_id }),
|
Keys.connectedUser({ project_id: projectId, client_id: clientId }),
|
||||||
'last_name',
|
'last_name',
|
||||||
user.last_name || ''
|
user.last_name || ''
|
||||||
)
|
)
|
||||||
multi.hset(
|
multi.hset(
|
||||||
Keys.connectedUser({ project_id, client_id }),
|
Keys.connectedUser({ project_id: projectId, client_id: clientId }),
|
||||||
'email',
|
'email',
|
||||||
user.email || ''
|
user.email || ''
|
||||||
)
|
)
|
||||||
|
|
||||||
if (cursorData) {
|
if (cursorData) {
|
||||||
multi.hset(
|
multi.hset(
|
||||||
Keys.connectedUser({ project_id, client_id }),
|
Keys.connectedUser({ project_id: projectId, client_id: clientId }),
|
||||||
'cursorData',
|
'cursorData',
|
||||||
JSON.stringify(cursorData)
|
JSON.stringify(cursorData)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
multi.expire(
|
multi.expire(
|
||||||
Keys.connectedUser({ project_id, client_id }),
|
Keys.connectedUser({ project_id: projectId, client_id: clientId }),
|
||||||
USER_TIMEOUT_IN_S
|
USER_TIMEOUT_IN_S
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -77,34 +74,39 @@ module.exports = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
refreshClient(project_id, client_id) {
|
refreshClient(projectId, clientId) {
|
||||||
logger.debug({ project_id, client_id }, 'refreshing connected client')
|
logger.debug({ projectId, clientId }, 'refreshing connected client')
|
||||||
const multi = rclient.multi()
|
const multi = rclient.multi()
|
||||||
multi.hset(
|
multi.hset(
|
||||||
Keys.connectedUser({ project_id, client_id }),
|
Keys.connectedUser({ project_id: projectId, client_id: clientId }),
|
||||||
'last_updated_at',
|
'last_updated_at',
|
||||||
Date.now()
|
Date.now()
|
||||||
)
|
)
|
||||||
multi.expire(
|
multi.expire(
|
||||||
Keys.connectedUser({ project_id, client_id }),
|
Keys.connectedUser({ project_id: projectId, client_id: clientId }),
|
||||||
USER_TIMEOUT_IN_S
|
USER_TIMEOUT_IN_S
|
||||||
)
|
)
|
||||||
multi.exec(function (err) {
|
multi.exec(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.err(
|
logger.err(
|
||||||
{ err, project_id, client_id },
|
{ err, projectId, clientId },
|
||||||
'problem refreshing connected client'
|
'problem refreshing connected client'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
markUserAsDisconnected(project_id, client_id, callback) {
|
markUserAsDisconnected(projectId, clientId, callback) {
|
||||||
logger.debug({ project_id, client_id }, 'marking user as disconnected')
|
logger.debug({ projectId, clientId }, 'marking user as disconnected')
|
||||||
const multi = rclient.multi()
|
const multi = rclient.multi()
|
||||||
multi.srem(Keys.clientsInProject({ project_id }), client_id)
|
multi.srem(Keys.clientsInProject({ project_id: projectId }), clientId)
|
||||||
multi.expire(Keys.clientsInProject({ project_id }), FOUR_DAYS_IN_S)
|
multi.expire(
|
||||||
multi.del(Keys.connectedUser({ project_id, client_id }))
|
Keys.clientsInProject({ project_id: projectId }),
|
||||||
|
FOUR_DAYS_IN_S
|
||||||
|
)
|
||||||
|
multi.del(
|
||||||
|
Keys.connectedUser({ project_id: projectId, client_id: clientId })
|
||||||
|
)
|
||||||
multi.exec(function (err) {
|
multi.exec(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
err = new OError('problem marking user as disconnected').withCause(err)
|
err = new OError('problem marking user as disconnected').withCause(err)
|
||||||
|
@ -113,24 +115,24 @@ module.exports = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
_getConnectedUser(project_id, client_id, callback) {
|
_getConnectedUser(projectId, clientId, callback) {
|
||||||
rclient.hgetall(
|
rclient.hgetall(
|
||||||
Keys.connectedUser({ project_id, client_id }),
|
Keys.connectedUser({ project_id: projectId, client_id: clientId }),
|
||||||
function (err, result) {
|
function (err, result) {
|
||||||
if (err) {
|
if (err) {
|
||||||
err = new OError('problem fetching connected user details', {
|
err = new OError('problem fetching connected user details', {
|
||||||
other_client_id: client_id,
|
other_client_id: clientId,
|
||||||
}).withCause(err)
|
}).withCause(err)
|
||||||
return callback(err)
|
return callback(err)
|
||||||
}
|
}
|
||||||
if (!(result && result.user_id)) {
|
if (!(result && result.user_id)) {
|
||||||
result = {
|
result = {
|
||||||
connected: false,
|
connected: false,
|
||||||
client_id,
|
client_id: clientId,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result.connected = true
|
result.connected = true
|
||||||
result.client_id = client_id
|
result.client_id = clientId
|
||||||
result.client_age =
|
result.client_age =
|
||||||
(Date.now() - parseInt(result.last_updated_at, 10)) / 1000
|
(Date.now() - parseInt(result.last_updated_at, 10)) / 1000
|
||||||
if (result.cursorData) {
|
if (result.cursorData) {
|
||||||
|
@ -138,7 +140,7 @@ module.exports = {
|
||||||
result.cursorData = JSON.parse(result.cursorData)
|
result.cursorData = JSON.parse(result.cursorData)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
OError.tag(e, 'error parsing cursorData JSON', {
|
OError.tag(e, 'error parsing cursorData JSON', {
|
||||||
other_client_id: client_id,
|
other_client_id: clientId,
|
||||||
cursorData: result.cursorData,
|
cursorData: result.cursorData,
|
||||||
})
|
})
|
||||||
return callback(e)
|
return callback(e)
|
||||||
|
@ -150,17 +152,17 @@ module.exports = {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
getConnectedUsers(project_id, callback) {
|
getConnectedUsers(projectId, callback) {
|
||||||
const self = this
|
const self = this
|
||||||
rclient.smembers(
|
rclient.smembers(
|
||||||
Keys.clientsInProject({ project_id }),
|
Keys.clientsInProject({ project_id: projectId }),
|
||||||
function (err, results) {
|
function (err, results) {
|
||||||
if (err) {
|
if (err) {
|
||||||
err = new OError('problem getting clients in project').withCause(err)
|
err = new OError('problem getting clients in project').withCause(err)
|
||||||
return callback(err)
|
return callback(err)
|
||||||
}
|
}
|
||||||
const jobs = results.map(
|
const jobs = results.map(
|
||||||
client_id => cb => self._getConnectedUser(project_id, client_id, cb)
|
clientId => cb => self._getConnectedUser(projectId, clientId, cb)
|
||||||
)
|
)
|
||||||
async.series(jobs, function (err, users) {
|
async.series(jobs, function (err, users) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
const logger = require('@overleaf/logger')
|
const logger = require('@overleaf/logger')
|
||||||
const settings = require('@overleaf/settings')
|
const settings = require('@overleaf/settings')
|
||||||
const RedisClientManager = require('./RedisClientManager')
|
const RedisClientManager = require('./RedisClientManager')
|
||||||
|
@ -49,18 +46,15 @@ module.exports = DocumentUpdaterController = {
|
||||||
|
|
||||||
handleRoomUpdates(rclientSubList) {
|
handleRoomUpdates(rclientSubList) {
|
||||||
const roomEvents = RoomManager.eventSource()
|
const roomEvents = RoomManager.eventSource()
|
||||||
roomEvents.on('doc-active', function (doc_id) {
|
roomEvents.on('doc-active', function (docId) {
|
||||||
const subscribePromises = rclientSubList.map(rclient =>
|
const subscribePromises = rclientSubList.map(rclient =>
|
||||||
ChannelManager.subscribe(rclient, 'applied-ops', doc_id)
|
ChannelManager.subscribe(rclient, 'applied-ops', docId)
|
||||||
)
|
|
||||||
RoomManager.emitOnCompletion(
|
|
||||||
subscribePromises,
|
|
||||||
`doc-subscribed-${doc_id}`
|
|
||||||
)
|
)
|
||||||
|
RoomManager.emitOnCompletion(subscribePromises, `doc-subscribed-${docId}`)
|
||||||
})
|
})
|
||||||
roomEvents.on('doc-empty', doc_id =>
|
roomEvents.on('doc-empty', docId =>
|
||||||
rclientSubList.map(rclient =>
|
rclientSubList.map(rclient =>
|
||||||
ChannelManager.unsubscribe(rclient, 'applied-ops', doc_id)
|
ChannelManager.unsubscribe(rclient, 'applied-ops', docId)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -104,9 +98,9 @@ module.exports = DocumentUpdaterController = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
_applyUpdateFromDocumentUpdater(io, doc_id, update) {
|
_applyUpdateFromDocumentUpdater(io, docId, update) {
|
||||||
let client
|
let client
|
||||||
const clientList = io.sockets.clients(doc_id)
|
const clientList = io.sockets.clients(docId)
|
||||||
// avoid unnecessary work if no clients are connected
|
// avoid unnecessary work if no clients are connected
|
||||||
if (clientList.length === 0) {
|
if (clientList.length === 0) {
|
||||||
return
|
return
|
||||||
|
@ -114,7 +108,7 @@ module.exports = DocumentUpdaterController = {
|
||||||
// send updates to clients
|
// send updates to clients
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{
|
{
|
||||||
doc_id,
|
docId,
|
||||||
version: update.v,
|
version: update.v,
|
||||||
source: update.meta && update.meta.source,
|
source: update.meta && update.meta.source,
|
||||||
socketIoClients: clientList.map(client => client.id),
|
socketIoClients: clientList.map(client => client.id),
|
||||||
|
@ -129,7 +123,7 @@ module.exports = DocumentUpdaterController = {
|
||||||
if (client.publicId === update.meta.source) {
|
if (client.publicId === update.meta.source) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{
|
{
|
||||||
doc_id,
|
docId,
|
||||||
version: update.v,
|
version: update.v,
|
||||||
source: update.meta.source,
|
source: update.meta.source,
|
||||||
},
|
},
|
||||||
|
@ -140,10 +134,10 @@ module.exports = DocumentUpdaterController = {
|
||||||
// Duplicate ops should just be sent back to sending client for acknowledgement
|
// Duplicate ops should just be sent back to sending client for acknowledgement
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{
|
{
|
||||||
doc_id,
|
docId,
|
||||||
version: update.v,
|
version: update.v,
|
||||||
source: update.meta.source,
|
source: update.meta.source,
|
||||||
client_id: client.id,
|
clientId: client.id,
|
||||||
},
|
},
|
||||||
'distributing update to collaborator'
|
'distributing update to collaborator'
|
||||||
)
|
)
|
||||||
|
@ -155,7 +149,7 @@ module.exports = DocumentUpdaterController = {
|
||||||
metrics.inc('socket-io.duplicate-clients', 0.1)
|
metrics.inc('socket-io.duplicate-clients', 0.1)
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{
|
{
|
||||||
doc_id,
|
docId,
|
||||||
socketIoClients: clientList.map(client => client.id),
|
socketIoClients: clientList.map(client => client.id),
|
||||||
},
|
},
|
||||||
'discarded duplicate clients'
|
'discarded duplicate clients'
|
||||||
|
@ -163,10 +157,10 @@ module.exports = DocumentUpdaterController = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_processErrorFromDocumentUpdater(io, doc_id, error, message) {
|
_processErrorFromDocumentUpdater(io, docId, error, message) {
|
||||||
for (const client of io.sockets.clients(doc_id)) {
|
for (const client of io.sockets.clients(docId)) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
{ err: error, doc_id, client_id: client.id },
|
{ err: error, docId, clientId: client.id },
|
||||||
'error from document updater, disconnecting client'
|
'error from document updater, disconnecting client'
|
||||||
)
|
)
|
||||||
client.emit('otUpdateError', error, message)
|
client.emit('otUpdateError', error, message)
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
const request = require('request')
|
const request = require('request')
|
||||||
const _ = require('underscore')
|
const _ = require('underscore')
|
||||||
const OError = require('@overleaf/o-error')
|
const OError = require('@overleaf/o-error')
|
||||||
|
@ -20,11 +17,11 @@ const rclient = require('@overleaf/redis-wrapper').createClient(
|
||||||
const Keys = settings.redis.documentupdater.key_schema
|
const Keys = settings.redis.documentupdater.key_schema
|
||||||
|
|
||||||
const DocumentUpdaterManager = {
|
const DocumentUpdaterManager = {
|
||||||
getDocument(project_id, doc_id, fromVersion, callback) {
|
getDocument(projectId, docId, fromVersion, callback) {
|
||||||
const timer = new metrics.Timer('get-document')
|
const timer = new metrics.Timer('get-document')
|
||||||
const url = `${settings.apis.documentupdater.url}/project/${project_id}/doc/${doc_id}?fromVersion=${fromVersion}`
|
const url = `${settings.apis.documentupdater.url}/project/${projectId}/doc/${docId}?fromVersion=${fromVersion}`
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{ project_id, doc_id, fromVersion },
|
{ projectId, docId, fromVersion },
|
||||||
'getting doc from document updater'
|
'getting doc from document updater'
|
||||||
)
|
)
|
||||||
request.get(url, function (err, res, body) {
|
request.get(url, function (err, res, body) {
|
||||||
|
@ -35,7 +32,7 @@ const DocumentUpdaterManager = {
|
||||||
}
|
}
|
||||||
if (res.statusCode >= 200 && res.statusCode < 300) {
|
if (res.statusCode >= 200 && res.statusCode < 300) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{ project_id, doc_id },
|
{ projectId, docId },
|
||||||
'got doc from document document updater'
|
'got doc from document document updater'
|
||||||
)
|
)
|
||||||
try {
|
try {
|
||||||
|
@ -56,18 +53,18 @@ const DocumentUpdaterManager = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
checkDocument(project_id, doc_id, callback) {
|
checkDocument(projectId, docId, callback) {
|
||||||
// in this call fromVersion = -1 means get document without docOps
|
// in this call fromVersion = -1 means get document without docOps
|
||||||
DocumentUpdaterManager.getDocument(project_id, doc_id, -1, callback)
|
DocumentUpdaterManager.getDocument(projectId, docId, -1, callback)
|
||||||
},
|
},
|
||||||
|
|
||||||
flushProjectToMongoAndDelete(project_id, callback) {
|
flushProjectToMongoAndDelete(projectId, callback) {
|
||||||
// this method is called when the last connected user leaves the project
|
// this method is called when the last connected user leaves the project
|
||||||
logger.debug({ project_id }, 'deleting project from document updater')
|
logger.debug({ projectId }, 'deleting project from document updater')
|
||||||
const timer = new metrics.Timer('delete.mongo.project')
|
const timer = new metrics.Timer('delete.mongo.project')
|
||||||
// flush the project in the background when all users have left
|
// flush the project in the background when all users have left
|
||||||
const url =
|
const url =
|
||||||
`${settings.apis.documentupdater.url}/project/${project_id}?background=true` +
|
`${settings.apis.documentupdater.url}/project/${projectId}?background=true` +
|
||||||
(settings.shutDownInProgress ? '&shutdown=true' : '')
|
(settings.shutDownInProgress ? '&shutdown=true' : '')
|
||||||
request.del(url, function (err, res) {
|
request.del(url, function (err, res) {
|
||||||
timer.done()
|
timer.done()
|
||||||
|
@ -75,7 +72,7 @@ const DocumentUpdaterManager = {
|
||||||
OError.tag(err, 'error deleting project from document updater')
|
OError.tag(err, 'error deleting project from document updater')
|
||||||
callback(err)
|
callback(err)
|
||||||
} else if (res.statusCode >= 200 && res.statusCode < 300) {
|
} else if (res.statusCode >= 200 && res.statusCode < 300) {
|
||||||
logger.debug({ project_id }, 'deleted project from document updater')
|
logger.debug({ projectId }, 'deleted project from document updater')
|
||||||
callback(null)
|
callback(null)
|
||||||
} else {
|
} else {
|
||||||
callback(
|
callback(
|
||||||
|
@ -97,7 +94,7 @@ const DocumentUpdaterManager = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
queueChange(project_id, doc_id, change, callback) {
|
queueChange(projectId, docId, change, callback) {
|
||||||
const allowedKeys = [
|
const allowedKeys = [
|
||||||
'doc',
|
'doc',
|
||||||
'op',
|
'op',
|
||||||
|
@ -122,11 +119,11 @@ const DocumentUpdaterManager = {
|
||||||
// record metric for each update added to queue
|
// record metric for each update added to queue
|
||||||
metrics.summary('redis.pendingUpdates', updateSize, { status: 'push' })
|
metrics.summary('redis.pendingUpdates', updateSize, { status: 'push' })
|
||||||
|
|
||||||
const doc_key = `${project_id}:${doc_id}`
|
const docKey = `${projectId}:${docId}`
|
||||||
// Push onto pendingUpdates for doc_id first, because once the doc updater
|
// Push onto pendingUpdates for doc_id first, because once the doc updater
|
||||||
// gets an entry on pending-updates-list, it starts processing.
|
// gets an entry on pending-updates-list, it starts processing.
|
||||||
rclient.rpush(
|
rclient.rpush(
|
||||||
Keys.pendingUpdates({ doc_id }),
|
Keys.pendingUpdates({ doc_id: docId }),
|
||||||
jsonChange,
|
jsonChange,
|
||||||
function (error) {
|
function (error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -134,7 +131,7 @@ const DocumentUpdaterManager = {
|
||||||
return callback(error)
|
return callback(error)
|
||||||
}
|
}
|
||||||
const queueKey = DocumentUpdaterManager._getPendingUpdateListKey()
|
const queueKey = DocumentUpdaterManager._getPendingUpdateListKey()
|
||||||
rclient.rpush(queueKey, doc_key, function (error) {
|
rclient.rpush(queueKey, docKey, function (error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
error = new OError('error pushing doc_id into redis')
|
error = new OError('error pushing doc_id into redis')
|
||||||
.withInfo({ queueKey })
|
.withInfo({ queueKey })
|
||||||
|
|
|
@ -39,7 +39,7 @@ module.exports = {
|
||||||
if (!this.RECONNECTED_CLIENTS[client.id]) {
|
if (!this.RECONNECTED_CLIENTS[client.id]) {
|
||||||
this.RECONNECTED_CLIENTS[client.id] = true
|
this.RECONNECTED_CLIENTS[client.id] = true
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{ client_id: client.id },
|
{ clientId: client.id },
|
||||||
'Asking client to reconnect gracefully'
|
'Asking client to reconnect gracefully'
|
||||||
)
|
)
|
||||||
client.emit('reconnectGracefully')
|
client.emit('reconnectGracefully')
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
let EventLogger
|
let EventLogger
|
||||||
const logger = require('@overleaf/logger')
|
const logger = require('@overleaf/logger')
|
||||||
const metrics = require('@overleaf/metrics')
|
const metrics = require('@overleaf/metrics')
|
||||||
|
@ -26,12 +23,12 @@ module.exports = EventLogger = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
checkEventOrder(channel, message_id) {
|
checkEventOrder(channel, messageId) {
|
||||||
if (typeof message_id !== 'string') {
|
if (typeof messageId !== 'string') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let result
|
let result
|
||||||
if (!(result = message_id.match(/^(.*)-(\d+)$/))) {
|
if (!(result = messageId.match(/^(.*)-(\d+)$/))) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const key = result[1]
|
const key = result[1]
|
||||||
|
@ -48,12 +45,12 @@ module.exports = EventLogger = {
|
||||||
}
|
}
|
||||||
if (count === previous) {
|
if (count === previous) {
|
||||||
metrics.inc(`event.${channel}.duplicate`)
|
metrics.inc(`event.${channel}.duplicate`)
|
||||||
logger.warn({ channel, message_id }, 'duplicate event')
|
logger.warn({ channel, messageId }, 'duplicate event')
|
||||||
return 'duplicate'
|
return 'duplicate'
|
||||||
} else {
|
} else {
|
||||||
metrics.inc(`event.${channel}.out-of-order`)
|
metrics.inc(`event.${channel}.out-of-order`)
|
||||||
logger.warn(
|
logger.warn(
|
||||||
{ channel, message_id, key, previous, count },
|
{ channel, messageId, key, previous, count },
|
||||||
'out of order event'
|
'out of order event'
|
||||||
)
|
)
|
||||||
return 'out-of-order'
|
return 'out-of-order'
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
const WebsocketLoadBalancer = require('./WebsocketLoadBalancer')
|
const WebsocketLoadBalancer = require('./WebsocketLoadBalancer')
|
||||||
const DrainManager = require('./DrainManager')
|
const DrainManager = require('./DrainManager')
|
||||||
const logger = require('@overleaf/logger')
|
const logger = require('@overleaf/logger')
|
||||||
|
@ -37,15 +34,15 @@ module.exports = {
|
||||||
|
|
||||||
disconnectClient(req, res, next) {
|
disconnectClient(req, res, next) {
|
||||||
const io = req.app.get('io')
|
const io = req.app.get('io')
|
||||||
const { client_id } = req.params
|
const { client_id: clientId } = req.params
|
||||||
const client = io.sockets.sockets[client_id]
|
const client = io.sockets.sockets[clientId]
|
||||||
|
|
||||||
if (!client) {
|
if (!client) {
|
||||||
logger.debug({ client_id }, 'api: client already disconnected')
|
logger.debug({ clientId }, 'api: client already disconnected')
|
||||||
res.sendStatus(404)
|
res.sendStatus(404)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.info({ client_id }, 'api: requesting client disconnect')
|
logger.info({ clientId }, 'api: requesting client disconnect')
|
||||||
client.on('disconnect', () => res.sendStatus(204))
|
client.on('disconnect', () => res.sendStatus(204))
|
||||||
client.disconnect()
|
client.disconnect()
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
|
|
||||||
let HttpController
|
let HttpController
|
||||||
module.exports = HttpController = {
|
module.exports = HttpController = {
|
||||||
// The code in this controller is hard to unit test because of a lot of
|
// The code in this controller is hard to unit test because of a lot of
|
||||||
|
@ -10,25 +6,25 @@ module.exports = HttpController = {
|
||||||
// and for checking internal state in acceptance tests. The acceptances tests
|
// and for checking internal state in acceptance tests. The acceptances tests
|
||||||
// should provide appropriate coverage.
|
// should provide appropriate coverage.
|
||||||
_getConnectedClientView(ioClient) {
|
_getConnectedClientView(ioClient) {
|
||||||
const client_id = ioClient.id
|
const clientId = ioClient.id
|
||||||
const {
|
const {
|
||||||
project_id,
|
project_id: projectId,
|
||||||
user_id,
|
user_id: userId,
|
||||||
first_name,
|
first_name: firstName,
|
||||||
last_name,
|
last_name: lastName,
|
||||||
email,
|
email,
|
||||||
connected_time,
|
connected_time: connectedTime,
|
||||||
} = ioClient.ol_context
|
} = ioClient.ol_context
|
||||||
const client = {
|
const client = {
|
||||||
client_id,
|
client_id: clientId,
|
||||||
project_id,
|
project_id: projectId,
|
||||||
user_id,
|
user_id: userId,
|
||||||
first_name,
|
first_name: firstName,
|
||||||
last_name,
|
last_name: lastName,
|
||||||
email,
|
email,
|
||||||
connected_time,
|
connected_time: connectedTime,
|
||||||
}
|
}
|
||||||
client.rooms = Object.keys(ioClient.manager.roomClients[client_id] || {})
|
client.rooms = Object.keys(ioClient.manager.roomClients[clientId] || {})
|
||||||
// drop the namespace
|
// drop the namespace
|
||||||
.filter(room => room !== '')
|
.filter(room => room !== '')
|
||||||
// room names are composed as '<NAMESPACE>/<ROOM>' and the default
|
// room names are composed as '<NAMESPACE>/<ROOM>' and the default
|
||||||
|
@ -45,9 +41,9 @@ module.exports = HttpController = {
|
||||||
},
|
},
|
||||||
|
|
||||||
getConnectedClient(req, res) {
|
getConnectedClient(req, res) {
|
||||||
const { client_id } = req.params
|
const { client_id: clientId } = req.params
|
||||||
const io = req.app.get('io')
|
const io = req.app.get('io')
|
||||||
const ioClient = io.sockets.sockets[client_id]
|
const ioClient = io.sockets.sockets[clientId]
|
||||||
if (!ioClient) {
|
if (!ioClient) {
|
||||||
res.sendStatus(404)
|
res.sendStatus(404)
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
const logger = require('@overleaf/logger')
|
const logger = require('@overleaf/logger')
|
||||||
const metrics = require('@overleaf/metrics')
|
const metrics = require('@overleaf/metrics')
|
||||||
const { EventEmitter } = require('events')
|
const { EventEmitter } = require('events')
|
||||||
|
@ -20,16 +17,16 @@ const RoomEvents = new EventEmitter() // emits {project,doc}-active and {project
|
||||||
// The pubsub side is handled by ChannelManager
|
// The pubsub side is handled by ChannelManager
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
joinProject(client, project_id, callback) {
|
joinProject(client, projectId, callback) {
|
||||||
this.joinEntity(client, 'project', project_id, callback)
|
this.joinEntity(client, 'project', projectId, callback)
|
||||||
},
|
},
|
||||||
|
|
||||||
joinDoc(client, doc_id, callback) {
|
joinDoc(client, docId, callback) {
|
||||||
this.joinEntity(client, 'doc', doc_id, callback)
|
this.joinEntity(client, 'doc', docId, callback)
|
||||||
},
|
},
|
||||||
|
|
||||||
leaveDoc(client, doc_id) {
|
leaveDoc(client, docId) {
|
||||||
this.leaveEntity(client, 'doc', doc_id)
|
this.leaveEntity(client, 'doc', docId)
|
||||||
},
|
},
|
||||||
|
|
||||||
leaveProjectAndDocs(client) {
|
leaveProjectAndDocs(client) {
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
const metrics = require('@overleaf/metrics')
|
const metrics = require('@overleaf/metrics')
|
||||||
const logger = require('@overleaf/logger')
|
const logger = require('@overleaf/logger')
|
||||||
const settings = require('@overleaf/settings')
|
const settings = require('@overleaf/settings')
|
||||||
|
@ -184,7 +181,7 @@ module.exports = Router = {
|
||||||
metrics.inc('socket-io.connection', 1, { status: client.transport })
|
metrics.inc('socket-io.connection', 1, { status: client.transport })
|
||||||
metrics.gauge('socket-io.clients', io.sockets.clients().length)
|
metrics.gauge('socket-io.clients', io.sockets.clients().length)
|
||||||
|
|
||||||
logger.debug({ session, client_id: client.id }, 'client connected')
|
logger.debug({ session, clientId: client.id }, 'client connected')
|
||||||
|
|
||||||
let user
|
let user
|
||||||
if (session && session.passport && session.passport.user) {
|
if (session && session.passport && session.passport.user) {
|
||||||
|
@ -230,11 +227,11 @@ module.exports = Router = {
|
||||||
disconnect: 1,
|
disconnect: 1,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const { project_id, anonymousAccessToken } = data
|
const { project_id: projectId, anonymousAccessToken } = data
|
||||||
// only allow connection to a single project
|
// only allow connection to a single project
|
||||||
if (
|
if (
|
||||||
client.ol_current_project_id &&
|
client.ol_current_project_id &&
|
||||||
project_id !== client.ol_current_project_id
|
projectId !== client.ol_current_project_id
|
||||||
) {
|
) {
|
||||||
return Router._handleError(
|
return Router._handleError(
|
||||||
callback,
|
callback,
|
||||||
|
@ -244,18 +241,18 @@ module.exports = Router = {
|
||||||
{ disconnect: 1 }
|
{ disconnect: 1 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
client.ol_current_project_id = project_id
|
client.ol_current_project_id = projectId
|
||||||
if (anonymousAccessToken) {
|
if (anonymousAccessToken) {
|
||||||
user.anonymousAccessToken = anonymousAccessToken
|
user.anonymousAccessToken = anonymousAccessToken
|
||||||
}
|
}
|
||||||
WebsocketController.joinProject(
|
WebsocketController.joinProject(
|
||||||
client,
|
client,
|
||||||
user,
|
user,
|
||||||
project_id,
|
projectId,
|
||||||
function (err, ...args) {
|
function (err, ...args) {
|
||||||
if (err) {
|
if (err) {
|
||||||
Router._handleError(callback, err, client, 'joinProject', {
|
Router._handleError(callback, err, client, 'joinProject', {
|
||||||
project_id,
|
project_id: projectId,
|
||||||
user_id: user._id,
|
user_id: user._id,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -281,7 +278,7 @@ module.exports = Router = {
|
||||||
// doc_id, fromVersion, callback
|
// doc_id, fromVersion, callback
|
||||||
// doc_id, options, callback
|
// doc_id, options, callback
|
||||||
// doc_id, fromVersion, options, callback
|
// doc_id, fromVersion, options, callback
|
||||||
client.on('joinDoc', function (doc_id, fromVersion, options, callback) {
|
client.on('joinDoc', function (docId, fromVersion, options, callback) {
|
||||||
if (typeof fromVersion === 'function' && !options) {
|
if (typeof fromVersion === 'function' && !options) {
|
||||||
callback = fromVersion
|
callback = fromVersion
|
||||||
fromVersion = -1
|
fromVersion = -1
|
||||||
|
@ -310,7 +307,7 @@ module.exports = Router = {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Joi.assert(
|
Joi.assert(
|
||||||
{ doc_id, fromVersion, options },
|
{ doc_id: docId, fromVersion, options },
|
||||||
Joi.object({
|
Joi.object({
|
||||||
doc_id: JOI_OBJECT_ID,
|
doc_id: JOI_OBJECT_ID,
|
||||||
fromVersion: Joi.number().integer(),
|
fromVersion: Joi.number().integer(),
|
||||||
|
@ -324,13 +321,13 @@ module.exports = Router = {
|
||||||
}
|
}
|
||||||
WebsocketController.joinDoc(
|
WebsocketController.joinDoc(
|
||||||
client,
|
client,
|
||||||
doc_id,
|
docId,
|
||||||
fromVersion,
|
fromVersion,
|
||||||
options,
|
options,
|
||||||
function (err, ...args) {
|
function (err, ...args) {
|
||||||
if (err) {
|
if (err) {
|
||||||
Router._handleError(callback, err, client, 'joinDoc', {
|
Router._handleError(callback, err, client, 'joinDoc', {
|
||||||
doc_id,
|
doc_id: docId,
|
||||||
fromVersion,
|
fromVersion,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -340,21 +337,21 @@ module.exports = Router = {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
client.on('leaveDoc', function (doc_id, callback) {
|
client.on('leaveDoc', function (docId, callback) {
|
||||||
if (typeof callback !== 'function') {
|
if (typeof callback !== 'function') {
|
||||||
return Router._handleInvalidArguments(client, 'leaveDoc', arguments)
|
return Router._handleInvalidArguments(client, 'leaveDoc', arguments)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Joi.assert(doc_id, JOI_OBJECT_ID)
|
Joi.assert(docId, JOI_OBJECT_ID)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return Router._handleError(callback, error, client, 'joinDoc', {
|
return Router._handleError(callback, error, client, 'joinDoc', {
|
||||||
disconnect: 1,
|
disconnect: 1,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
WebsocketController.leaveDoc(client, doc_id, function (err, ...args) {
|
WebsocketController.leaveDoc(client, docId, function (err, ...args) {
|
||||||
if (err) {
|
if (err) {
|
||||||
Router._handleError(callback, err, client, 'leaveDoc', {
|
Router._handleError(callback, err, client, 'leaveDoc', {
|
||||||
doc_id,
|
doc_id: docId,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
callback(null, ...args)
|
callback(null, ...args)
|
||||||
|
@ -421,7 +418,7 @@ module.exports = Router = {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
client.on('applyOtUpdate', function (doc_id, update, callback) {
|
client.on('applyOtUpdate', function (docId, update, callback) {
|
||||||
if (typeof callback !== 'function') {
|
if (typeof callback !== 'function') {
|
||||||
return Router._handleInvalidArguments(
|
return Router._handleInvalidArguments(
|
||||||
client,
|
client,
|
||||||
|
@ -431,7 +428,7 @@ module.exports = Router = {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Joi.assert(
|
Joi.assert(
|
||||||
{ doc_id, update },
|
{ doc_id: docId, update },
|
||||||
Joi.object({
|
Joi.object({
|
||||||
doc_id: JOI_OBJECT_ID,
|
doc_id: JOI_OBJECT_ID,
|
||||||
update: Joi.object().required(),
|
update: Joi.object().required(),
|
||||||
|
@ -444,12 +441,12 @@ module.exports = Router = {
|
||||||
}
|
}
|
||||||
WebsocketController.applyOtUpdate(
|
WebsocketController.applyOtUpdate(
|
||||||
client,
|
client,
|
||||||
doc_id,
|
docId,
|
||||||
update,
|
update,
|
||||||
function (err) {
|
function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
Router._handleError(callback, err, client, 'applyOtUpdate', {
|
Router._handleError(callback, err, client, 'applyOtUpdate', {
|
||||||
doc_id,
|
doc_id: docId,
|
||||||
update,
|
update,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
const request = require('request')
|
const request = require('request')
|
||||||
const OError = require('@overleaf/o-error')
|
const OError = require('@overleaf/o-error')
|
||||||
const settings = require('@overleaf/settings')
|
const settings = require('@overleaf/settings')
|
||||||
|
@ -13,10 +10,10 @@ const {
|
||||||
} = require('./Errors')
|
} = require('./Errors')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
joinProject(project_id, user, callback) {
|
joinProject(projectId, user, callback) {
|
||||||
const user_id = user._id
|
const userId = user._id
|
||||||
logger.debug({ project_id, user_id }, 'sending join project request to web')
|
logger.debug({ projectId, userId }, 'sending join project request to web')
|
||||||
const url = `${settings.apis.web.url}/project/${project_id}/join`
|
const url = `${settings.apis.web.url}/project/${projectId}/join`
|
||||||
const headers = {}
|
const headers = {}
|
||||||
if (user.anonymousAccessToken) {
|
if (user.anonymousAccessToken) {
|
||||||
headers['x-sl-anonymous-access-token'] = user.anonymousAccessToken
|
headers['x-sl-anonymous-access-token'] = user.anonymousAccessToken
|
||||||
|
@ -24,7 +21,7 @@ module.exports = {
|
||||||
request.post(
|
request.post(
|
||||||
{
|
{
|
||||||
url,
|
url,
|
||||||
qs: { user_id },
|
qs: { user_id: userId },
|
||||||
auth: {
|
auth: {
|
||||||
user: settings.apis.web.user,
|
user: settings.apis.web.user,
|
||||||
pass: settings.apis.web.pass,
|
pass: settings.apis.web.pass,
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
const OError = require('@overleaf/o-error')
|
const OError = require('@overleaf/o-error')
|
||||||
const logger = require('@overleaf/logger')
|
const logger = require('@overleaf/logger')
|
||||||
const metrics = require('@overleaf/metrics')
|
const metrics = require('@overleaf/metrics')
|
||||||
|
@ -23,7 +20,7 @@ module.exports = WebsocketController = {
|
||||||
// compatible protocol changes. Use only in extreme need.
|
// compatible protocol changes. Use only in extreme need.
|
||||||
PROTOCOL_VERSION: 2,
|
PROTOCOL_VERSION: 2,
|
||||||
|
|
||||||
joinProject(client, user, project_id, callback) {
|
joinProject(client, user, projectId, callback) {
|
||||||
if (client.disconnected) {
|
if (client.disconnected) {
|
||||||
metrics.inc('editor.join-project.disconnected', 1, {
|
metrics.inc('editor.join-project.disconnected', 1, {
|
||||||
status: 'immediately',
|
status: 'immediately',
|
||||||
|
@ -31,20 +28,20 @@ module.exports = WebsocketController = {
|
||||||
return callback()
|
return callback()
|
||||||
}
|
}
|
||||||
|
|
||||||
const user_id = user._id
|
const userId = user._id
|
||||||
logger.info(
|
logger.info(
|
||||||
{
|
{
|
||||||
user_id,
|
userId,
|
||||||
project_id,
|
projectId,
|
||||||
client_id: client.id,
|
clientId: client.id,
|
||||||
remote_ip: client.remoteIp,
|
remoteIp: client.remoteIp,
|
||||||
user_agent: client.userAgent,
|
userAgent: client.userAgent,
|
||||||
},
|
},
|
||||||
'user joining project'
|
'user joining project'
|
||||||
)
|
)
|
||||||
metrics.inc('editor.join-project', 1, { status: client.transport })
|
metrics.inc('editor.join-project', 1, { status: client.transport })
|
||||||
WebApiManager.joinProject(
|
WebApiManager.joinProject(
|
||||||
project_id,
|
projectId,
|
||||||
user,
|
user,
|
||||||
function (error, project, privilegeLevel, isRestrictedUser) {
|
function (error, project, privilegeLevel, isRestrictedUser) {
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -52,7 +49,7 @@ module.exports = WebsocketController = {
|
||||||
}
|
}
|
||||||
if (client.disconnected) {
|
if (client.disconnected) {
|
||||||
logger.info(
|
logger.info(
|
||||||
{ user_id, project_id, client_id: client.id },
|
{ userId, projectId, clientId: client.id },
|
||||||
'client disconnected before joining project'
|
'client disconnected before joining project'
|
||||||
)
|
)
|
||||||
metrics.inc('editor.join-project.disconnected', 1, {
|
metrics.inc('editor.join-project.disconnected', 1, {
|
||||||
|
@ -67,8 +64,8 @@ module.exports = WebsocketController = {
|
||||||
|
|
||||||
client.ol_context = {}
|
client.ol_context = {}
|
||||||
client.ol_context.privilege_level = privilegeLevel
|
client.ol_context.privilege_level = privilegeLevel
|
||||||
client.ol_context.user_id = user_id
|
client.ol_context.user_id = userId
|
||||||
client.ol_context.project_id = project_id
|
client.ol_context.project_id = projectId
|
||||||
client.ol_context.owner_id = project.owner && project.owner._id
|
client.ol_context.owner_id = project.owner && project.owner._id
|
||||||
client.ol_context.first_name = user.first_name
|
client.ol_context.first_name = user.first_name
|
||||||
client.ol_context.last_name = user.last_name
|
client.ol_context.last_name = user.last_name
|
||||||
|
@ -78,15 +75,15 @@ module.exports = WebsocketController = {
|
||||||
client.ol_context.login_count = user.loginCount
|
client.ol_context.login_count = user.loginCount
|
||||||
client.ol_context.is_restricted_user = !!isRestrictedUser
|
client.ol_context.is_restricted_user = !!isRestrictedUser
|
||||||
|
|
||||||
RoomManager.joinProject(client, project_id, function (err) {
|
RoomManager.joinProject(client, projectId, function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return callback(err)
|
return callback(err)
|
||||||
}
|
}
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{
|
{
|
||||||
user_id,
|
userId,
|
||||||
project_id,
|
projectId,
|
||||||
client_id: client.id,
|
clientId: client.id,
|
||||||
privilegeLevel,
|
privilegeLevel,
|
||||||
isRestrictedUser,
|
isRestrictedUser,
|
||||||
},
|
},
|
||||||
|
@ -102,14 +99,14 @@ module.exports = WebsocketController = {
|
||||||
|
|
||||||
// No need to block for setting the user as connected in the cursor tracking
|
// No need to block for setting the user as connected in the cursor tracking
|
||||||
ConnectedUsersManager.updateUserPosition(
|
ConnectedUsersManager.updateUserPosition(
|
||||||
project_id,
|
projectId,
|
||||||
client.publicId,
|
client.publicId,
|
||||||
user,
|
user,
|
||||||
null,
|
null,
|
||||||
function (err) {
|
function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
{ err, project_id, user_id, client_id: client.id },
|
{ err, projectId, userId, clientId: client.id },
|
||||||
'background cursor update failed'
|
'background cursor update failed'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -124,30 +121,30 @@ module.exports = WebsocketController = {
|
||||||
// is determined by FLUSH_IF_EMPTY_DELAY.
|
// is determined by FLUSH_IF_EMPTY_DELAY.
|
||||||
FLUSH_IF_EMPTY_DELAY: 500, // ms
|
FLUSH_IF_EMPTY_DELAY: 500, // ms
|
||||||
leaveProject(io, client, callback) {
|
leaveProject(io, client, callback) {
|
||||||
const { project_id, user_id } = client.ol_context
|
const { project_id: projectId, user_id: userId } = client.ol_context
|
||||||
if (!project_id) {
|
if (!projectId) {
|
||||||
return callback()
|
return callback()
|
||||||
} // client did not join project
|
} // client did not join project
|
||||||
|
|
||||||
metrics.inc('editor.leave-project', 1, { status: client.transport })
|
metrics.inc('editor.leave-project', 1, { status: client.transport })
|
||||||
logger.info(
|
logger.info(
|
||||||
{ project_id, user_id, client_id: client.id },
|
{ projectId, userId, clientId: client.id },
|
||||||
'client leaving project'
|
'client leaving project'
|
||||||
)
|
)
|
||||||
WebsocketLoadBalancer.emitToRoom(
|
WebsocketLoadBalancer.emitToRoom(
|
||||||
project_id,
|
projectId,
|
||||||
'clientTracking.clientDisconnected',
|
'clientTracking.clientDisconnected',
|
||||||
client.publicId
|
client.publicId
|
||||||
)
|
)
|
||||||
|
|
||||||
// We can do this in the background
|
// We can do this in the background
|
||||||
ConnectedUsersManager.markUserAsDisconnected(
|
ConnectedUsersManager.markUserAsDisconnected(
|
||||||
project_id,
|
projectId,
|
||||||
client.publicId,
|
client.publicId,
|
||||||
function (err) {
|
function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.error(
|
logger.error(
|
||||||
{ err, project_id, user_id, client_id: client.id },
|
{ err, projectId, userId, clientId: client.id },
|
||||||
'error marking client as disconnected'
|
'error marking client as disconnected'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -156,15 +153,15 @@ module.exports = WebsocketController = {
|
||||||
|
|
||||||
RoomManager.leaveProjectAndDocs(client)
|
RoomManager.leaveProjectAndDocs(client)
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
const remainingClients = io.sockets.clients(project_id)
|
const remainingClients = io.sockets.clients(projectId)
|
||||||
if (remainingClients.length === 0) {
|
if (remainingClients.length === 0) {
|
||||||
// Flush project in the background
|
// Flush project in the background
|
||||||
DocumentUpdaterManager.flushProjectToMongoAndDelete(
|
DocumentUpdaterManager.flushProjectToMongoAndDelete(
|
||||||
project_id,
|
projectId,
|
||||||
function (err) {
|
function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.error(
|
logger.error(
|
||||||
{ err, project_id, user_id, client_id: client.id },
|
{ err, projectId, userId, clientId: client.id },
|
||||||
'error flushing to doc updater after leaving project'
|
'error flushing to doc updater after leaving project'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -175,7 +172,7 @@ module.exports = WebsocketController = {
|
||||||
}, WebsocketController.FLUSH_IF_EMPTY_DELAY)
|
}, WebsocketController.FLUSH_IF_EMPTY_DELAY)
|
||||||
},
|
},
|
||||||
|
|
||||||
joinDoc(client, doc_id, fromVersion, options, callback) {
|
joinDoc(client, docId, fromVersion, options, callback) {
|
||||||
if (client.disconnected) {
|
if (client.disconnected) {
|
||||||
metrics.inc('editor.join-doc.disconnected', 1, { status: 'immediately' })
|
metrics.inc('editor.join-doc.disconnected', 1, { status: 'immediately' })
|
||||||
return callback()
|
return callback()
|
||||||
|
@ -183,18 +180,22 @@ module.exports = WebsocketController = {
|
||||||
|
|
||||||
const joinLeaveEpoch = ++client.joinLeaveEpoch
|
const joinLeaveEpoch = ++client.joinLeaveEpoch
|
||||||
metrics.inc('editor.join-doc', 1, { status: client.transport })
|
metrics.inc('editor.join-doc', 1, { status: client.transport })
|
||||||
const { project_id, user_id, is_restricted_user } = client.ol_context
|
const {
|
||||||
if (!project_id) {
|
project_id: projectId,
|
||||||
|
user_id: userId,
|
||||||
|
is_restricted_user: isRestrictedUser,
|
||||||
|
} = client.ol_context
|
||||||
|
if (!projectId) {
|
||||||
return callback(new NotJoinedError())
|
return callback(new NotJoinedError())
|
||||||
}
|
}
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{ user_id, project_id, doc_id, fromVersion, client_id: client.id },
|
{ userId, projectId, docId, fromVersion, clientId: client.id },
|
||||||
'client joining doc'
|
'client joining doc'
|
||||||
)
|
)
|
||||||
|
|
||||||
WebsocketController._assertClientAuthorization(
|
WebsocketController._assertClientAuthorization(
|
||||||
client,
|
client,
|
||||||
doc_id,
|
docId,
|
||||||
function (error) {
|
function (error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
return callback(error)
|
return callback(error)
|
||||||
|
@ -212,7 +213,7 @@ module.exports = WebsocketController = {
|
||||||
}
|
}
|
||||||
// ensure the per-doc applied-ops channel is subscribed before sending the
|
// ensure the per-doc applied-ops channel is subscribed before sending the
|
||||||
// doc to the client, so that no events are missed.
|
// doc to the client, so that no events are missed.
|
||||||
RoomManager.joinDoc(client, doc_id, function (error) {
|
RoomManager.joinDoc(client, docId, function (error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
return callback(error)
|
return callback(error)
|
||||||
}
|
}
|
||||||
|
@ -225,8 +226,8 @@ module.exports = WebsocketController = {
|
||||||
}
|
}
|
||||||
|
|
||||||
DocumentUpdaterManager.getDocument(
|
DocumentUpdaterManager.getDocument(
|
||||||
project_id,
|
projectId,
|
||||||
doc_id,
|
docId,
|
||||||
fromVersion,
|
fromVersion,
|
||||||
function (error, lines, version, ranges, ops) {
|
function (error, lines, version, ranges, ops) {
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -240,7 +241,7 @@ module.exports = WebsocketController = {
|
||||||
return callback()
|
return callback()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_restricted_user && ranges && ranges.comments) {
|
if (isRestrictedUser && ranges && ranges.comments) {
|
||||||
ranges.comments = []
|
ranges.comments = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,14 +282,14 @@ module.exports = WebsocketController = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthorizationManager.addAccessToDoc(client, doc_id, () => {})
|
AuthorizationManager.addAccessToDoc(client, docId, () => {})
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{
|
{
|
||||||
user_id,
|
userId,
|
||||||
project_id,
|
projectId,
|
||||||
doc_id,
|
docId,
|
||||||
fromVersion,
|
fromVersion,
|
||||||
client_id: client.id,
|
clientId: client.id,
|
||||||
},
|
},
|
||||||
'client joined doc'
|
'client joined doc'
|
||||||
)
|
)
|
||||||
|
@ -300,7 +301,7 @@ module.exports = WebsocketController = {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
_assertClientAuthorization(client, doc_id, callback) {
|
_assertClientAuthorization(client, docId, callback) {
|
||||||
// Check for project-level access first
|
// Check for project-level access first
|
||||||
AuthorizationManager.assertClientCanViewProject(client, function (error) {
|
AuthorizationManager.assertClientCanViewProject(client, function (error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -309,20 +310,20 @@ module.exports = WebsocketController = {
|
||||||
// Check for doc-level access next
|
// Check for doc-level access next
|
||||||
AuthorizationManager.assertClientCanViewProjectAndDoc(
|
AuthorizationManager.assertClientCanViewProjectAndDoc(
|
||||||
client,
|
client,
|
||||||
doc_id,
|
docId,
|
||||||
function (error) {
|
function (error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
// No cached access, check docupdater
|
// No cached access, check docupdater
|
||||||
const { project_id } = client.ol_context
|
const { project_id: projectId } = client.ol_context
|
||||||
DocumentUpdaterManager.checkDocument(
|
DocumentUpdaterManager.checkDocument(
|
||||||
project_id,
|
projectId,
|
||||||
doc_id,
|
docId,
|
||||||
function (error) {
|
function (error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
return callback(error)
|
return callback(error)
|
||||||
} else {
|
} else {
|
||||||
// Success
|
// Success
|
||||||
AuthorizationManager.addAccessToDoc(client, doc_id, callback)
|
AuthorizationManager.addAccessToDoc(client, docId, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -335,16 +336,16 @@ module.exports = WebsocketController = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
leaveDoc(client, doc_id, callback) {
|
leaveDoc(client, docId, callback) {
|
||||||
// client may have disconnected, but we have to cleanup internal state.
|
// client may have disconnected, but we have to cleanup internal state.
|
||||||
client.joinLeaveEpoch++
|
client.joinLeaveEpoch++
|
||||||
metrics.inc('editor.leave-doc', 1, { status: client.transport })
|
metrics.inc('editor.leave-doc', 1, { status: client.transport })
|
||||||
const { project_id, user_id } = client.ol_context
|
const { project_id: projectId, user_id: userId } = client.ol_context
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{ user_id, project_id, doc_id, client_id: client.id },
|
{ userId, projectId, docId, clientId: client.id },
|
||||||
'client leaving doc'
|
'client leaving doc'
|
||||||
)
|
)
|
||||||
RoomManager.leaveDoc(client, doc_id)
|
RoomManager.leaveDoc(client, docId)
|
||||||
// we could remove permission when user leaves a doc, but because
|
// we could remove permission when user leaves a doc, but because
|
||||||
// the connection is per-project, we continue to allow access
|
// the connection is per-project, we continue to allow access
|
||||||
// after the initial joinDoc since we know they are already authorised.
|
// after the initial joinDoc since we know they are already authorised.
|
||||||
|
@ -360,10 +361,15 @@ module.exports = WebsocketController = {
|
||||||
metrics.inc('editor.update-client-position', 0.1, {
|
metrics.inc('editor.update-client-position', 0.1, {
|
||||||
status: client.transport,
|
status: client.transport,
|
||||||
})
|
})
|
||||||
const { project_id, first_name, last_name, email, user_id } =
|
const {
|
||||||
client.ol_context
|
project_id: projectId,
|
||||||
|
first_name: firstName,
|
||||||
|
last_name: lastName,
|
||||||
|
email,
|
||||||
|
user_id: userId,
|
||||||
|
} = client.ol_context
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{ user_id, project_id, client_id: client.id, cursorData },
|
{ userId, projectId, clientId: client.id, cursorData },
|
||||||
'updating client position'
|
'updating client position'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -373,36 +379,36 @@ module.exports = WebsocketController = {
|
||||||
function (error) {
|
function (error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{ err: error, client_id: client.id, project_id, user_id },
|
{ err: error, clientId: client.id, projectId, userId },
|
||||||
"silently ignoring unauthorized updateClientPosition. Client likely hasn't called joinProject yet."
|
"silently ignoring unauthorized updateClientPosition. Client likely hasn't called joinProject yet."
|
||||||
)
|
)
|
||||||
return callback()
|
return callback()
|
||||||
}
|
}
|
||||||
cursorData.id = client.publicId
|
cursorData.id = client.publicId
|
||||||
if (user_id) {
|
if (userId) {
|
||||||
cursorData.user_id = user_id
|
cursorData.user_id = userId
|
||||||
}
|
}
|
||||||
if (email) {
|
if (email) {
|
||||||
cursorData.email = email
|
cursorData.email = email
|
||||||
}
|
}
|
||||||
// Don't store anonymous users in redis to avoid influx
|
// Don't store anonymous users in redis to avoid influx
|
||||||
if (!user_id || user_id === 'anonymous-user') {
|
if (!userId || userId === 'anonymous-user') {
|
||||||
cursorData.name = ''
|
cursorData.name = ''
|
||||||
// consistent async behaviour
|
// consistent async behaviour
|
||||||
setTimeout(callback)
|
setTimeout(callback)
|
||||||
} else {
|
} else {
|
||||||
cursorData.name =
|
cursorData.name =
|
||||||
first_name && last_name
|
firstName && lastName
|
||||||
? `${first_name} ${last_name}`
|
? `${firstName} ${lastName}`
|
||||||
: first_name || last_name || ''
|
: firstName || lastName || ''
|
||||||
ConnectedUsersManager.updateUserPosition(
|
ConnectedUsersManager.updateUserPosition(
|
||||||
project_id,
|
projectId,
|
||||||
client.publicId,
|
client.publicId,
|
||||||
{
|
{
|
||||||
first_name,
|
first_name: firstName,
|
||||||
last_name,
|
last_name: lastName,
|
||||||
email,
|
email,
|
||||||
_id: user_id,
|
_id: userId,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
row: cursorData.row,
|
row: cursorData.row,
|
||||||
|
@ -413,7 +419,7 @@ module.exports = WebsocketController = {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
WebsocketLoadBalancer.emitToRoom(
|
WebsocketLoadBalancer.emitToRoom(
|
||||||
project_id,
|
projectId,
|
||||||
'clientTracking.clientUpdated',
|
'clientTracking.clientUpdated',
|
||||||
cursorData
|
cursorData
|
||||||
)
|
)
|
||||||
|
@ -429,32 +435,36 @@ module.exports = WebsocketController = {
|
||||||
}
|
}
|
||||||
|
|
||||||
metrics.inc('editor.get-connected-users', { status: client.transport })
|
metrics.inc('editor.get-connected-users', { status: client.transport })
|
||||||
const { project_id, user_id, is_restricted_user } = client.ol_context
|
const {
|
||||||
if (is_restricted_user) {
|
project_id: projectId,
|
||||||
|
user_id: userId,
|
||||||
|
is_restricted_user: isRestrictedUser,
|
||||||
|
} = client.ol_context
|
||||||
|
if (isRestrictedUser) {
|
||||||
return callback(null, [])
|
return callback(null, [])
|
||||||
}
|
}
|
||||||
if (!project_id) {
|
if (!projectId) {
|
||||||
return callback(new NotJoinedError())
|
return callback(new NotJoinedError())
|
||||||
}
|
}
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{ user_id, project_id, client_id: client.id },
|
{ userId, projectId, clientId: client.id },
|
||||||
'getting connected users'
|
'getting connected users'
|
||||||
)
|
)
|
||||||
AuthorizationManager.assertClientCanViewProject(client, function (error) {
|
AuthorizationManager.assertClientCanViewProject(client, function (error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
return callback(error)
|
return callback(error)
|
||||||
}
|
}
|
||||||
WebsocketLoadBalancer.emitToRoom(project_id, 'clientTracking.refresh')
|
WebsocketLoadBalancer.emitToRoom(projectId, 'clientTracking.refresh')
|
||||||
setTimeout(
|
setTimeout(
|
||||||
() =>
|
() =>
|
||||||
ConnectedUsersManager.getConnectedUsers(
|
ConnectedUsersManager.getConnectedUsers(
|
||||||
project_id,
|
projectId,
|
||||||
function (error, users) {
|
function (error, users) {
|
||||||
if (error) {
|
if (error) {
|
||||||
return callback(error)
|
return callback(error)
|
||||||
}
|
}
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{ user_id, project_id, client_id: client.id },
|
{ userId, projectId, clientId: client.id },
|
||||||
'got connected users'
|
'got connected users'
|
||||||
)
|
)
|
||||||
callback(null, users)
|
callback(null, users)
|
||||||
|
@ -465,16 +475,16 @@ module.exports = WebsocketController = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
applyOtUpdate(client, doc_id, update, callback) {
|
applyOtUpdate(client, docId, update, callback) {
|
||||||
// client may have disconnected, but we can submit their update to doc-updater anyways.
|
// client may have disconnected, but we can submit their update to doc-updater anyways.
|
||||||
const { user_id, project_id } = client.ol_context
|
const { user_id: userId, project_id: projectId } = client.ol_context
|
||||||
if (!project_id) {
|
if (!projectId) {
|
||||||
return callback(new NotJoinedError())
|
return callback(new NotJoinedError())
|
||||||
}
|
}
|
||||||
|
|
||||||
WebsocketController._assertClientCanApplyUpdate(
|
WebsocketController._assertClientCanApplyUpdate(
|
||||||
client,
|
client,
|
||||||
doc_id,
|
docId,
|
||||||
update,
|
update,
|
||||||
function (error) {
|
function (error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -490,30 +500,30 @@ module.exports = WebsocketController = {
|
||||||
update.meta = {}
|
update.meta = {}
|
||||||
}
|
}
|
||||||
update.meta.source = client.publicId
|
update.meta.source = client.publicId
|
||||||
update.meta.user_id = user_id
|
update.meta.user_id = userId
|
||||||
metrics.inc('editor.doc-update', 0.3, { status: client.transport })
|
metrics.inc('editor.doc-update', 0.3, { status: client.transport })
|
||||||
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{
|
{
|
||||||
user_id,
|
userId,
|
||||||
doc_id,
|
docId,
|
||||||
project_id,
|
projectId,
|
||||||
client_id: client.id,
|
clientId: client.id,
|
||||||
version: update.v,
|
version: update.v,
|
||||||
},
|
},
|
||||||
'sending update to doc updater'
|
'sending update to doc updater'
|
||||||
)
|
)
|
||||||
|
|
||||||
DocumentUpdaterManager.queueChange(
|
DocumentUpdaterManager.queueChange(
|
||||||
project_id,
|
projectId,
|
||||||
doc_id,
|
docId,
|
||||||
update,
|
update,
|
||||||
function (error) {
|
function (error) {
|
||||||
if ((error && error.message) === 'update is too large') {
|
if ((error && error.message) === 'update is too large') {
|
||||||
metrics.inc('update_too_large')
|
metrics.inc('update_too_large')
|
||||||
const { updateSize } = error.info
|
const { updateSize } = error.info
|
||||||
logger.warn(
|
logger.warn(
|
||||||
{ user_id, project_id, doc_id, updateSize },
|
{ userId, projectId, docId, updateSize },
|
||||||
'update is too large'
|
'update is too large'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -522,8 +532,8 @@ module.exports = WebsocketController = {
|
||||||
|
|
||||||
// trigger an out-of-sync error
|
// trigger an out-of-sync error
|
||||||
const message = {
|
const message = {
|
||||||
project_id,
|
project_id: projectId,
|
||||||
doc_id,
|
doc_id: docId,
|
||||||
error: 'update is too large',
|
error: 'update is too large',
|
||||||
}
|
}
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
|
@ -552,10 +562,10 @@ module.exports = WebsocketController = {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
_assertClientCanApplyUpdate(client, doc_id, update, callback) {
|
_assertClientCanApplyUpdate(client, docId, update, callback) {
|
||||||
AuthorizationManager.assertClientCanEditProjectAndDoc(
|
AuthorizationManager.assertClientCanEditProjectAndDoc(
|
||||||
client,
|
client,
|
||||||
doc_id,
|
docId,
|
||||||
function (error) {
|
function (error) {
|
||||||
if (
|
if (
|
||||||
error &&
|
error &&
|
||||||
|
@ -565,7 +575,7 @@ module.exports = WebsocketController = {
|
||||||
// This might be a comment op, which we only need read-only priveleges for
|
// This might be a comment op, which we only need read-only priveleges for
|
||||||
AuthorizationManager.assertClientCanViewProjectAndDoc(
|
AuthorizationManager.assertClientCanViewProjectAndDoc(
|
||||||
client,
|
client,
|
||||||
doc_id,
|
docId,
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
const Settings = require('@overleaf/settings')
|
const Settings = require('@overleaf/settings')
|
||||||
const logger = require('@overleaf/logger')
|
const logger = require('@overleaf/logger')
|
||||||
const RedisClientManager = require('./RedisClientManager')
|
const RedisClientManager = require('./RedisClientManager')
|
||||||
|
@ -28,8 +25,8 @@ module.exports = WebsocketLoadBalancer = {
|
||||||
rclientPubList: RedisClientManager.createClientList(Settings.redis.pubsub),
|
rclientPubList: RedisClientManager.createClientList(Settings.redis.pubsub),
|
||||||
rclientSubList: RedisClientManager.createClientList(Settings.redis.pubsub),
|
rclientSubList: RedisClientManager.createClientList(Settings.redis.pubsub),
|
||||||
|
|
||||||
emitToRoom(room_id, message, ...payload) {
|
emitToRoom(roomId, message, ...payload) {
|
||||||
if (!room_id) {
|
if (!roomId) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
{ message, payload },
|
{ message, payload },
|
||||||
'no room_id provided, ignoring emitToRoom'
|
'no room_id provided, ignoring emitToRoom'
|
||||||
|
@ -37,17 +34,17 @@ module.exports = WebsocketLoadBalancer = {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const data = JSON.stringify({
|
const data = JSON.stringify({
|
||||||
room_id,
|
room_id: roomId,
|
||||||
message,
|
message,
|
||||||
payload,
|
payload,
|
||||||
})
|
})
|
||||||
logger.debug(
|
logger.debug(
|
||||||
{ room_id, message, payload, length: data.length },
|
{ roomId, message, payload, length: data.length },
|
||||||
'emitting to room'
|
'emitting to room'
|
||||||
)
|
)
|
||||||
|
|
||||||
this.rclientPubList.map(rclientPub =>
|
this.rclientPubList.map(rclientPub =>
|
||||||
ChannelManager.publish(rclientPub, 'editor-events', room_id, data)
|
ChannelManager.publish(rclientPub, 'editor-events', roomId, data)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -74,18 +71,18 @@ module.exports = WebsocketLoadBalancer = {
|
||||||
|
|
||||||
handleRoomUpdates(rclientSubList) {
|
handleRoomUpdates(rclientSubList) {
|
||||||
const roomEvents = RoomManager.eventSource()
|
const roomEvents = RoomManager.eventSource()
|
||||||
roomEvents.on('project-active', function (project_id) {
|
roomEvents.on('project-active', function (projectId) {
|
||||||
const subscribePromises = rclientSubList.map(rclient =>
|
const subscribePromises = rclientSubList.map(rclient =>
|
||||||
ChannelManager.subscribe(rclient, 'editor-events', project_id)
|
ChannelManager.subscribe(rclient, 'editor-events', projectId)
|
||||||
)
|
)
|
||||||
RoomManager.emitOnCompletion(
|
RoomManager.emitOnCompletion(
|
||||||
subscribePromises,
|
subscribePromises,
|
||||||
`project-subscribed-${project_id}`
|
`project-subscribed-${projectId}`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
roomEvents.on('project-empty', project_id =>
|
roomEvents.on('project-empty', projectId =>
|
||||||
rclientSubList.map(rclient =>
|
rclientSubList.map(rclient =>
|
||||||
ChannelManager.unsubscribe(rclient, 'editor-events', project_id)
|
ChannelManager.unsubscribe(rclient, 'editor-events', projectId)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -107,8 +104,8 @@ module.exports = WebsocketLoadBalancer = {
|
||||||
{
|
{
|
||||||
channel,
|
channel,
|
||||||
message: message.message,
|
message: message.message,
|
||||||
room_id: message.room_id,
|
roomId: message.room_id,
|
||||||
message_id: message._id,
|
messageId: message._id,
|
||||||
socketIoClients: clientList.map(client => client.id),
|
socketIoClients: clientList.map(client => client.id),
|
||||||
},
|
},
|
||||||
'refreshing client list'
|
'refreshing client list'
|
||||||
|
@ -128,7 +125,7 @@ module.exports = WebsocketLoadBalancer = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const is_restricted_message =
|
const isRestrictedMessage =
|
||||||
!RESTRICTED_USER_MESSAGE_TYPE_PASS_LIST.includes(message.message)
|
!RESTRICTED_USER_MESSAGE_TYPE_PASS_LIST.includes(message.message)
|
||||||
|
|
||||||
// send messages only to unique clients (due to duplicate entries in io.sockets.clients)
|
// send messages only to unique clients (due to duplicate entries in io.sockets.clients)
|
||||||
|
@ -136,7 +133,7 @@ module.exports = WebsocketLoadBalancer = {
|
||||||
.clients(message.room_id)
|
.clients(message.room_id)
|
||||||
.filter(
|
.filter(
|
||||||
client =>
|
client =>
|
||||||
!(is_restricted_message && client.ol_context.is_restricted_user)
|
!(isRestrictedMessage && client.ol_context.is_restricted_user)
|
||||||
)
|
)
|
||||||
|
|
||||||
// avoid unnecessary work if no clients are connected
|
// avoid unnecessary work if no clients are connected
|
||||||
|
@ -147,8 +144,8 @@ module.exports = WebsocketLoadBalancer = {
|
||||||
{
|
{
|
||||||
channel,
|
channel,
|
||||||
message: message.message,
|
message: message.message,
|
||||||
room_id: message.room_id,
|
roomId: message.room_id,
|
||||||
message_id: message._id,
|
messageId: message._id,
|
||||||
socketIoClients: clientList.map(client => client.id),
|
socketIoClients: clientList.map(client => client.id),
|
||||||
},
|
},
|
||||||
'distributing event to clients'
|
'distributing event to clients'
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable
|
/* eslint-disable
|
||||||
camelcase,
|
|
||||||
no-return-assign,
|
no-return-assign,
|
||||||
*/
|
*/
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
// TODO: This file was created by bulk-decaffeinate.
|
||||||
|
@ -68,9 +67,9 @@ describe('applyOtUpdate', function () {
|
||||||
{
|
{
|
||||||
privilegeLevel: 'readAndWrite',
|
privilegeLevel: 'readAndWrite',
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -80,8 +79,8 @@ describe('applyOtUpdate', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -120,8 +119,8 @@ describe('applyOtUpdate', function () {
|
||||||
it('should push the doc into the pending updates list', function (done) {
|
it('should push the doc into the pending updates list', function (done) {
|
||||||
getPendingUpdatesList((error, ...rest) => {
|
getPendingUpdatesList((error, ...rest) => {
|
||||||
if (error) return done(error)
|
if (error) return done(error)
|
||||||
const [doc_id] = Array.from(rest[0])
|
const [docId] = Array.from(rest[0])
|
||||||
doc_id.should.equal(`${this.project_id}:${this.doc_id}`)
|
docId.should.equal(`${this.project_id}:${this.doc_id}`)
|
||||||
return done()
|
return done()
|
||||||
})
|
})
|
||||||
return null
|
return null
|
||||||
|
@ -187,9 +186,9 @@ describe('applyOtUpdate', function () {
|
||||||
{
|
{
|
||||||
privilegeLevel: 'readAndWrite',
|
privilegeLevel: 'readAndWrite',
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -199,8 +198,8 @@ describe('applyOtUpdate', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -284,9 +283,9 @@ describe('applyOtUpdate', function () {
|
||||||
{
|
{
|
||||||
privilegeLevel: 'readOnly',
|
privilegeLevel: 'readOnly',
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -296,8 +295,8 @@ describe('applyOtUpdate', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -374,9 +373,9 @@ describe('applyOtUpdate', function () {
|
||||||
{
|
{
|
||||||
privilegeLevel: 'readOnly',
|
privilegeLevel: 'readOnly',
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -386,8 +385,8 @@ describe('applyOtUpdate', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -426,8 +425,8 @@ describe('applyOtUpdate', function () {
|
||||||
it('should push the doc into the pending updates list', function (done) {
|
it('should push the doc into the pending updates list', function (done) {
|
||||||
getPendingUpdatesList((error, ...rest) => {
|
getPendingUpdatesList((error, ...rest) => {
|
||||||
if (error) return done(error)
|
if (error) return done(error)
|
||||||
const [doc_id] = Array.from(rest[0])
|
const [docId] = Array.from(rest[0])
|
||||||
doc_id.should.equal(`${this.project_id}:${this.doc_id}`)
|
docId.should.equal(`${this.project_id}:${this.doc_id}`)
|
||||||
return done()
|
return done()
|
||||||
})
|
})
|
||||||
return null
|
return null
|
||||||
|
@ -487,9 +486,9 @@ describe('applyOtUpdate', function () {
|
||||||
{
|
{
|
||||||
privilegeLevel: 'readOnly',
|
privilegeLevel: 'readOnly',
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -499,8 +498,8 @@ describe('applyOtUpdate', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -574,9 +573,9 @@ describe('applyOtUpdate', function () {
|
||||||
{
|
{
|
||||||
privilegeLevel: 'readAndWrite',
|
privilegeLevel: 'readAndWrite',
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -586,8 +585,8 @@ describe('applyOtUpdate', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable
|
/* eslint-disable
|
||||||
camelcase,
|
|
||||||
no-unused-vars,
|
no-unused-vars,
|
||||||
*/
|
*/
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
// TODO: This file was created by bulk-decaffeinate.
|
||||||
|
@ -30,10 +29,10 @@ describe('clientTracking', function () {
|
||||||
privilegeLevel: 'owner',
|
privilegeLevel: 'owner',
|
||||||
project: { name: 'Test Project' },
|
project: { name: 'Test Project' },
|
||||||
},
|
},
|
||||||
(error, { user_id, project_id }) => {
|
(error, { user_id: userId, project_id: projectId }) => {
|
||||||
if (error) return done(error)
|
if (error) return done(error)
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
return cb()
|
return cb()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -43,8 +42,8 @@ describe('clientTracking', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -155,10 +154,10 @@ describe('clientTracking', function () {
|
||||||
project: { name: 'Test Project' },
|
project: { name: 'Test Project' },
|
||||||
publicAccess: 'readAndWrite',
|
publicAccess: 'readAndWrite',
|
||||||
},
|
},
|
||||||
(error, { user_id, project_id }) => {
|
(error, { user_id: userId, project_id: projectId }) => {
|
||||||
if (error) return done(error)
|
if (error) return done(error)
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
return cb()
|
return cb()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -168,8 +167,8 @@ describe('clientTracking', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
// TODO: This file was created by bulk-decaffeinate.
|
||||||
// Fix any style issues and re-enable lint.
|
// Fix any style issues and re-enable lint.
|
||||||
/*
|
/*
|
||||||
|
@ -35,9 +32,9 @@ describe('DrainManagerTests', function () {
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return done()
|
return done()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable
|
/* eslint-disable
|
||||||
camelcase,
|
|
||||||
no-return-assign,
|
no-return-assign,
|
||||||
*/
|
*/
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
// TODO: This file was created by bulk-decaffeinate.
|
||||||
|
@ -34,8 +33,8 @@ describe('EarlyDisconnect', function () {
|
||||||
// slow down web-api requests to force the race condition
|
// slow down web-api requests to force the race condition
|
||||||
let joinProject
|
let joinProject
|
||||||
this.actualWebAPIjoinProject = joinProject = MockWebServer.joinProject
|
this.actualWebAPIjoinProject = joinProject = MockWebServer.joinProject
|
||||||
return (MockWebServer.joinProject = (project_id, user_id, cb) =>
|
return (MockWebServer.joinProject = (projectId, userId, cb) =>
|
||||||
setTimeout(() => joinProject(project_id, user_id, cb), 300))
|
setTimeout(() => joinProject(projectId, userId, cb), 300))
|
||||||
})
|
})
|
||||||
|
|
||||||
after(function () {
|
after(function () {
|
||||||
|
@ -53,9 +52,9 @@ describe('EarlyDisconnect', function () {
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb()
|
return cb()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -114,9 +113,9 @@ describe('EarlyDisconnect', function () {
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb()
|
return cb()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -144,8 +143,8 @@ describe('EarlyDisconnect', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -202,9 +201,9 @@ describe('EarlyDisconnect', function () {
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb()
|
return cb()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -232,8 +231,8 @@ describe('EarlyDisconnect', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
// TODO: This file was created by bulk-decaffeinate.
|
||||||
// Fix any style issues and re-enable lint.
|
// Fix any style issues and re-enable lint.
|
||||||
/*
|
/*
|
||||||
|
@ -20,10 +17,10 @@ const FixturesManager = require('./helpers/FixturesManager')
|
||||||
describe('HttpControllerTests', function () {
|
describe('HttpControllerTests', function () {
|
||||||
describe('without a user', function () {
|
describe('without a user', function () {
|
||||||
return it('should return 404 for the client view', function (done) {
|
return it('should return 404 for the client view', function (done) {
|
||||||
const client_id = 'not-existing'
|
const clientId = 'not-existing'
|
||||||
return request.get(
|
return request.get(
|
||||||
{
|
{
|
||||||
url: `/clients/${client_id}`,
|
url: `/clients/${clientId}`,
|
||||||
json: true,
|
json: true,
|
||||||
},
|
},
|
||||||
(error, response, data) => {
|
(error, response, data) => {
|
||||||
|
@ -46,9 +43,9 @@ describe('HttpControllerTests', function () {
|
||||||
{
|
{
|
||||||
privilegeLevel: 'owner',
|
privilegeLevel: 'owner',
|
||||||
},
|
},
|
||||||
(error, { project_id, user_id }) => {
|
(error, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(error)
|
return cb(error)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -58,8 +55,8 @@ describe('HttpControllerTests', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{},
|
{},
|
||||||
(error, { doc_id }) => {
|
(error, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(error)
|
return cb(error)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable
|
/* eslint-disable
|
||||||
camelcase,
|
|
||||||
no-return-assign,
|
no-return-assign,
|
||||||
*/
|
*/
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
// TODO: This file was created by bulk-decaffeinate.
|
||||||
|
@ -35,9 +34,9 @@ describe('joinDoc', function () {
|
||||||
{
|
{
|
||||||
privilegeLevel: 'readAndWrite',
|
privilegeLevel: 'readAndWrite',
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -52,8 +51,8 @@ describe('joinDoc', function () {
|
||||||
ops: this.ops,
|
ops: this.ops,
|
||||||
ranges: this.ranges,
|
ranges: this.ranges,
|
||||||
},
|
},
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -123,9 +122,9 @@ describe('joinDoc', function () {
|
||||||
{
|
{
|
||||||
privilegeLevel: 'readOnly',
|
privilegeLevel: 'readOnly',
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -140,8 +139,8 @@ describe('joinDoc', function () {
|
||||||
ops: this.ops,
|
ops: this.ops,
|
||||||
ranges: this.ranges,
|
ranges: this.ranges,
|
||||||
},
|
},
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -211,9 +210,9 @@ describe('joinDoc', function () {
|
||||||
{
|
{
|
||||||
privilegeLevel: 'owner',
|
privilegeLevel: 'owner',
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -228,8 +227,8 @@ describe('joinDoc', function () {
|
||||||
ops: this.ops,
|
ops: this.ops,
|
||||||
ranges: this.ranges,
|
ranges: this.ranges,
|
||||||
},
|
},
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -303,9 +302,9 @@ describe('joinDoc', function () {
|
||||||
{
|
{
|
||||||
privilegeLevel: 'owner',
|
privilegeLevel: 'owner',
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -320,8 +319,8 @@ describe('joinDoc', function () {
|
||||||
ops: this.ops,
|
ops: this.ops,
|
||||||
ranges: this.ranges,
|
ranges: this.ranges,
|
||||||
},
|
},
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -389,9 +388,9 @@ describe('joinDoc', function () {
|
||||||
{
|
{
|
||||||
privilegeLevel: 'readAndWrite',
|
privilegeLevel: 'readAndWrite',
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -406,8 +405,8 @@ describe('joinDoc', function () {
|
||||||
ops: this.ops,
|
ops: this.ops,
|
||||||
ranges: this.ranges,
|
ranges: this.ranges,
|
||||||
},
|
},
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -479,9 +478,9 @@ describe('joinDoc', function () {
|
||||||
{
|
{
|
||||||
privilegeLevel: 'readAndWrite',
|
privilegeLevel: 'readAndWrite',
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -496,8 +495,8 @@ describe('joinDoc', function () {
|
||||||
ops: this.ops,
|
ops: this.ops,
|
||||||
ranges: this.ranges,
|
ranges: this.ranges,
|
||||||
},
|
},
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -570,9 +569,9 @@ describe('joinDoc', function () {
|
||||||
{
|
{
|
||||||
privilegeLevel: 'readAndWrite',
|
privilegeLevel: 'readAndWrite',
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -587,8 +586,8 @@ describe('joinDoc', function () {
|
||||||
ops: this.ops,
|
ops: this.ops,
|
||||||
ranges: this.ranges,
|
ranges: this.ranges,
|
||||||
},
|
},
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
// TODO: This file was created by bulk-decaffeinate.
|
||||||
// Fix any style issues and re-enable lint.
|
// Fix any style issues and re-enable lint.
|
||||||
/*
|
/*
|
||||||
|
@ -30,9 +27,9 @@ describe('joinProject', function () {
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -127,9 +124,9 @@ describe('joinProject', function () {
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -189,9 +186,9 @@ describe('joinProject', function () {
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
cb(e)
|
cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -251,9 +248,9 @@ describe('joinProject', function () {
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
cb(e)
|
cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -346,9 +343,9 @@ describe('joinProject', function () {
|
||||||
name: 'Other Project',
|
name: 'Other Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.other_project_id = project_id
|
this.other_project_id = projectId
|
||||||
this.other_user_id = user_id
|
this.other_user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -363,9 +360,9 @@ describe('joinProject', function () {
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable
|
/* eslint-disable
|
||||||
camelcase,
|
|
||||||
no-return-assign,
|
no-return-assign,
|
||||||
no-unused-vars,
|
no-unused-vars,
|
||||||
*/
|
*/
|
||||||
|
@ -48,9 +47,9 @@ describe('leaveDoc', function () {
|
||||||
{
|
{
|
||||||
privilegeLevel: 'readAndWrite',
|
privilegeLevel: 'readAndWrite',
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -60,8 +59,8 @@ describe('leaveDoc', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable
|
/* eslint-disable
|
||||||
camelcase,
|
|
||||||
no-throw-literal,
|
no-throw-literal,
|
||||||
*/
|
*/
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
// TODO: This file was created by bulk-decaffeinate.
|
||||||
|
@ -37,9 +36,9 @@ describe('leaveProject', function () {
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb()
|
return cb()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -93,8 +92,8 @@ describe('leaveProject', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -184,9 +183,9 @@ describe('leaveProject', function () {
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb()
|
return cb()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -214,8 +213,8 @@ describe('leaveProject', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -44,9 +44,7 @@ There is additional meta-data that UserItems and SessionItems may use to skip
|
||||||
UserItem: { hasOwnProject: true, setup(cb) { cb(null, { project_id, ... }) }}
|
UserItem: { hasOwnProject: true, setup(cb) { cb(null, { project_id, ... }) }}
|
||||||
SessionItem: { needsOwnProject: true }
|
SessionItem: { needsOwnProject: true }
|
||||||
*/
|
*/
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
const { expect } = require('chai')
|
const { expect } = require('chai')
|
||||||
const async = require('async')
|
const async = require('async')
|
||||||
|
|
||||||
|
@ -58,11 +56,11 @@ const Keys = settings.redis.documentupdater.key_schema
|
||||||
const redis = require('@overleaf/redis-wrapper')
|
const redis = require('@overleaf/redis-wrapper')
|
||||||
const rclient = redis.createClient(settings.redis.pubsub)
|
const rclient = redis.createClient(settings.redis.pubsub)
|
||||||
|
|
||||||
function getPendingUpdates(doc_id, cb) {
|
function getPendingUpdates(docId, cb) {
|
||||||
rclient.lrange(Keys.pendingUpdates({ doc_id }), 0, 10, cb)
|
rclient.lrange(Keys.pendingUpdates({ doc_id: docId }), 0, 10, cb)
|
||||||
}
|
}
|
||||||
function cleanupPreviousUpdates(doc_id, cb) {
|
function cleanupPreviousUpdates(docId, cb) {
|
||||||
rclient.del(Keys.pendingUpdates({ doc_id }), cb)
|
rclient.del(Keys.pendingUpdates({ doc_id: docId }), cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('MatrixTests', function () {
|
describe('MatrixTests', function () {
|
||||||
|
@ -72,10 +70,10 @@ describe('MatrixTests', function () {
|
||||||
before(function setupPrivateProject(done) {
|
before(function setupPrivateProject(done) {
|
||||||
FixturesManager.setUpEditorSession(
|
FixturesManager.setUpEditorSession(
|
||||||
{ privilegeLevel: 'owner' },
|
{ privilegeLevel: 'owner' },
|
||||||
(err, { project_id, doc_id }) => {
|
(err, { project_id: projectId, doc_id: docId }) => {
|
||||||
if (err) return done(err)
|
if (err) return done(err)
|
||||||
privateProjectId = project_id
|
privateProjectId = projectId
|
||||||
privateDocId = doc_id
|
privateDocId = docId
|
||||||
privateClient = RealTimeClient.connect()
|
privateClient = RealTimeClient.connect()
|
||||||
privateClient.on('connectionAccepted', () => {
|
privateClient.on('connectionAccepted', () => {
|
||||||
privateClient.emit(
|
privateClient.emit(
|
||||||
|
@ -96,9 +94,9 @@ describe('MatrixTests', function () {
|
||||||
{
|
{
|
||||||
publicAccess: 'readAndWrite',
|
publicAccess: 'readAndWrite',
|
||||||
},
|
},
|
||||||
(err, { project_id, doc_id }) => {
|
(err, { project_id: projectId, doc_id: docId }) => {
|
||||||
readWriteProjectId = project_id
|
readWriteProjectId = projectId
|
||||||
readWriteDocId = doc_id
|
readWriteDocId = docId
|
||||||
done(err)
|
done(err)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -118,11 +116,11 @@ describe('MatrixTests', function () {
|
||||||
|
|
||||||
registered: {
|
registered: {
|
||||||
setup(cb) {
|
setup(cb) {
|
||||||
const user_id = FixturesManager.getRandomId()
|
const userId = FixturesManager.getRandomId()
|
||||||
RealTimeClient.setSession(
|
RealTimeClient.setSession(
|
||||||
{
|
{
|
||||||
user: {
|
user: {
|
||||||
_id: user_id,
|
_id: userId,
|
||||||
first_name: 'Joe',
|
first_name: 'Joe',
|
||||||
last_name: 'Bloggs',
|
last_name: 'Bloggs',
|
||||||
},
|
},
|
||||||
|
@ -130,7 +128,7 @@ describe('MatrixTests', function () {
|
||||||
err => {
|
err => {
|
||||||
if (err) return cb(err)
|
if (err) return cb(err)
|
||||||
cb(null, {
|
cb(null, {
|
||||||
user_id,
|
user_id: userId,
|
||||||
client: RealTimeClient.connect(),
|
client: RealTimeClient.connect(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -142,12 +140,12 @@ describe('MatrixTests', function () {
|
||||||
setup(cb) {
|
setup(cb) {
|
||||||
FixturesManager.setUpEditorSession(
|
FixturesManager.setUpEditorSession(
|
||||||
{ privilegeLevel: 'owner' },
|
{ privilegeLevel: 'owner' },
|
||||||
(err, { project_id, user_id, doc_id }) => {
|
(err, { project_id: projectId, user_id: userId, doc_id: docId }) => {
|
||||||
if (err) return cb(err)
|
if (err) return cb(err)
|
||||||
cb(null, {
|
cb(null, {
|
||||||
user_id,
|
user_id: userId,
|
||||||
project_id,
|
project_id: projectId,
|
||||||
doc_id,
|
doc_id: docId,
|
||||||
client: RealTimeClient.connect(),
|
client: RealTimeClient.connect(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable
|
/* eslint-disable
|
||||||
camelcase,
|
|
||||||
no-return-assign,
|
no-return-assign,
|
||||||
*/
|
*/
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
// TODO: This file was created by bulk-decaffeinate.
|
||||||
|
@ -36,9 +35,9 @@ describe('PubSubRace', function () {
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb()
|
return cb()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -66,8 +65,8 @@ describe('PubSubRace', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -112,9 +111,9 @@ describe('PubSubRace', function () {
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb()
|
return cb()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -142,8 +141,8 @@ describe('PubSubRace', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -195,9 +194,9 @@ describe('PubSubRace', function () {
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb()
|
return cb()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -225,8 +224,8 @@ describe('PubSubRace', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -277,9 +276,9 @@ describe('PubSubRace', function () {
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb()
|
return cb()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -307,8 +306,8 @@ describe('PubSubRace', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable
|
/* eslint-disable
|
||||||
camelcase,
|
|
||||||
no-unused-vars,
|
no-unused-vars,
|
||||||
*/
|
*/
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
// TODO: This file was created by bulk-decaffeinate.
|
||||||
|
@ -36,10 +35,10 @@ describe('receiveUpdate', function () {
|
||||||
privilegeLevel: 'owner',
|
privilegeLevel: 'owner',
|
||||||
project: { name: 'Test Project' },
|
project: { name: 'Test Project' },
|
||||||
},
|
},
|
||||||
(error, { user_id, project_id }) => {
|
(error, { user_id: userId, project_id: projectId }) => {
|
||||||
if (error) return done(error)
|
if (error) return done(error)
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
return cb()
|
return cb()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -49,8 +48,8 @@ describe('receiveUpdate', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id,
|
this.project_id,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id }) => {
|
(e, { doc_id: docId }) => {
|
||||||
this.doc_id = doc_id
|
this.doc_id = docId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -100,13 +99,10 @@ describe('receiveUpdate', function () {
|
||||||
privilegeLevel: 'owner',
|
privilegeLevel: 'owner',
|
||||||
project: { name: 'Test Project' },
|
project: { name: 'Test Project' },
|
||||||
},
|
},
|
||||||
(
|
(error, { user_id: userIdSecond, project_id: projectIdSecond }) => {
|
||||||
error,
|
|
||||||
{ user_id: user_id_second, project_id: project_id_second }
|
|
||||||
) => {
|
|
||||||
if (error) return done(error)
|
if (error) return done(error)
|
||||||
this.user_id_second = user_id_second
|
this.user_id_second = userIdSecond
|
||||||
this.project_id_second = project_id_second
|
this.project_id_second = projectIdSecond
|
||||||
return cb()
|
return cb()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -116,8 +112,8 @@ describe('receiveUpdate', function () {
|
||||||
return FixturesManager.setUpDoc(
|
return FixturesManager.setUpDoc(
|
||||||
this.project_id_second,
|
this.project_id_second,
|
||||||
{ lines: this.lines, version: this.version, ops: this.ops },
|
{ lines: this.lines, version: this.version, ops: this.ops },
|
||||||
(e, { doc_id: doc_id_second }) => {
|
(e, { doc_id: docIdSecond }) => {
|
||||||
this.doc_id_second = doc_id_second
|
this.doc_id_second = docIdSecond
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
// TODO: This file was created by bulk-decaffeinate.
|
||||||
// Fix any style issues and re-enable lint.
|
// Fix any style issues and re-enable lint.
|
||||||
/*
|
/*
|
||||||
|
@ -34,9 +31,9 @@ describe('Router', function () {
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -84,9 +81,9 @@ describe('Router', function () {
|
||||||
name: 'Test Project',
|
name: 'Test Project',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
(e, { project_id, user_id }) => {
|
(e, { project_id: projectId, user_id: userId }) => {
|
||||||
this.project_id = project_id
|
this.project_id = projectId
|
||||||
this.user_id = user_id
|
this.user_id = userId
|
||||||
return cb(e)
|
return cb(e)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
*/
|
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
// TODO: This file was created by bulk-decaffeinate.
|
||||||
// Fix any style issues and re-enable lint.
|
// Fix any style issues and re-enable lint.
|
||||||
/*
|
/*
|
||||||
|
@ -31,16 +28,21 @@ module.exports = FixturesManager = {
|
||||||
if (!options.project) {
|
if (!options.project) {
|
||||||
options.project = { name: 'Test Project' }
|
options.project = { name: 'Test Project' }
|
||||||
}
|
}
|
||||||
const { project_id, user_id, privilegeLevel, project, publicAccess } =
|
const {
|
||||||
options
|
project_id: projectId,
|
||||||
|
user_id: userId,
|
||||||
|
privilegeLevel,
|
||||||
|
project,
|
||||||
|
publicAccess,
|
||||||
|
} = options
|
||||||
|
|
||||||
const privileges = {}
|
const privileges = {}
|
||||||
privileges[user_id] = privilegeLevel
|
privileges[userId] = privilegeLevel
|
||||||
if (publicAccess) {
|
if (publicAccess) {
|
||||||
privileges['anonymous-user'] = publicAccess
|
privileges['anonymous-user'] = publicAccess
|
||||||
}
|
}
|
||||||
|
|
||||||
MockWebServer.createMockProject(project_id, privileges, project)
|
MockWebServer.createMockProject(projectId, privileges, project)
|
||||||
return MockWebServer.run(error => {
|
return MockWebServer.run(error => {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
throw error
|
throw error
|
||||||
|
@ -48,7 +50,7 @@ module.exports = FixturesManager = {
|
||||||
return RealTimeClient.setSession(
|
return RealTimeClient.setSession(
|
||||||
{
|
{
|
||||||
user: {
|
user: {
|
||||||
_id: user_id,
|
_id: userId,
|
||||||
first_name: 'Joe',
|
first_name: 'Joe',
|
||||||
last_name: 'Bloggs',
|
last_name: 'Bloggs',
|
||||||
},
|
},
|
||||||
|
@ -58,8 +60,8 @@ module.exports = FixturesManager = {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
return callback(null, {
|
return callback(null, {
|
||||||
project_id,
|
project_id: projectId,
|
||||||
user_id,
|
user_id: userId,
|
||||||
privilegeLevel,
|
privilegeLevel,
|
||||||
project,
|
project,
|
||||||
})
|
})
|
||||||
|
@ -68,7 +70,7 @@ module.exports = FixturesManager = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
setUpDoc(project_id, options, callback) {
|
setUpDoc(projectId, options, callback) {
|
||||||
if (options == null) {
|
if (options == null) {
|
||||||
options = {}
|
options = {}
|
||||||
}
|
}
|
||||||
|
@ -87,9 +89,9 @@ module.exports = FixturesManager = {
|
||||||
if (!options.ops) {
|
if (!options.ops) {
|
||||||
options.ops = ['mock', 'ops']
|
options.ops = ['mock', 'ops']
|
||||||
}
|
}
|
||||||
const { doc_id, lines, version, ops, ranges } = options
|
const { doc_id: docId, lines, version, ops, ranges } = options
|
||||||
|
|
||||||
MockDocUpdaterServer.createMockDoc(project_id, doc_id, {
|
MockDocUpdaterServer.createMockDoc(projectId, docId, {
|
||||||
lines,
|
lines,
|
||||||
version,
|
version,
|
||||||
ops,
|
ops,
|
||||||
|
@ -99,7 +101,13 @@ module.exports = FixturesManager = {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
return callback(null, { project_id, doc_id, lines, version, ops })
|
return callback(null, {
|
||||||
|
project_id: projectId,
|
||||||
|
doc_id: docId,
|
||||||
|
lines,
|
||||||
|
version,
|
||||||
|
ops,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable
|
/* eslint-disable
|
||||||
camelcase,
|
|
||||||
no-return-assign,
|
no-return-assign,
|
||||||
*/
|
*/
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
// TODO: This file was created by bulk-decaffeinate.
|
||||||
|
@ -17,26 +16,26 @@ const express = require('express')
|
||||||
module.exports = MockDocUpdaterServer = {
|
module.exports = MockDocUpdaterServer = {
|
||||||
docs: {},
|
docs: {},
|
||||||
|
|
||||||
createMockDoc(project_id, doc_id, data) {
|
createMockDoc(projectId, docId, data) {
|
||||||
return (MockDocUpdaterServer.docs[`${project_id}:${doc_id}`] = data)
|
return (MockDocUpdaterServer.docs[`${projectId}:${docId}`] = data)
|
||||||
},
|
},
|
||||||
|
|
||||||
getDocument(project_id, doc_id, fromVersion, callback) {
|
getDocument(projectId, docId, fromVersion, callback) {
|
||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
callback = function () {}
|
callback = function () {}
|
||||||
}
|
}
|
||||||
return callback(null, MockDocUpdaterServer.docs[`${project_id}:${doc_id}`])
|
return callback(null, MockDocUpdaterServer.docs[`${projectId}:${docId}`])
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteProject: sinon.stub().callsArg(1),
|
deleteProject: sinon.stub().callsArg(1),
|
||||||
|
|
||||||
getDocumentRequest(req, res, next) {
|
getDocumentRequest(req, res, next) {
|
||||||
const { project_id, doc_id } = req.params
|
const { project_id: projectId, doc_id: docId } = req.params
|
||||||
let { fromVersion } = req.query
|
let { fromVersion } = req.query
|
||||||
fromVersion = parseInt(fromVersion, 10)
|
fromVersion = parseInt(fromVersion, 10)
|
||||||
return MockDocUpdaterServer.getDocument(
|
return MockDocUpdaterServer.getDocument(
|
||||||
project_id,
|
projectId,
|
||||||
doc_id,
|
docId,
|
||||||
fromVersion,
|
fromVersion,
|
||||||
(error, data) => {
|
(error, data) => {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
|
@ -51,8 +50,8 @@ module.exports = MockDocUpdaterServer = {
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteProjectRequest(req, res, next) {
|
deleteProjectRequest(req, res, next) {
|
||||||
const { project_id } = req.params
|
const { project_id: projectId } = req.params
|
||||||
return MockDocUpdaterServer.deleteProject(project_id, error => {
|
return MockDocUpdaterServer.deleteProject(projectId, error => {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
return next(error)
|
return next(error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable
|
/* eslint-disable
|
||||||
camelcase,
|
|
||||||
no-return-assign,
|
no-return-assign,
|
||||||
*/
|
*/
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
// TODO: This file was created by bulk-decaffeinate.
|
||||||
|
@ -18,41 +17,41 @@ module.exports = MockWebServer = {
|
||||||
projects: {},
|
projects: {},
|
||||||
privileges: {},
|
privileges: {},
|
||||||
|
|
||||||
createMockProject(project_id, privileges, project) {
|
createMockProject(projectId, privileges, project) {
|
||||||
MockWebServer.privileges[project_id] = privileges
|
MockWebServer.privileges[projectId] = privileges
|
||||||
return (MockWebServer.projects[project_id] = project)
|
return (MockWebServer.projects[projectId] = project)
|
||||||
},
|
},
|
||||||
|
|
||||||
joinProject(project_id, user_id, callback) {
|
joinProject(projectId, userId, callback) {
|
||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
callback = function () {}
|
callback = function () {}
|
||||||
}
|
}
|
||||||
return callback(
|
return callback(
|
||||||
null,
|
null,
|
||||||
MockWebServer.projects[project_id],
|
MockWebServer.projects[projectId],
|
||||||
MockWebServer.privileges[project_id][user_id] ||
|
MockWebServer.privileges[projectId][userId] ||
|
||||||
MockWebServer.privileges[project_id]['anonymous-user']
|
MockWebServer.privileges[projectId]['anonymous-user']
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
joinProjectRequest(req, res, next) {
|
joinProjectRequest(req, res, next) {
|
||||||
const { project_id } = req.params
|
const { project_id: projectId } = req.params
|
||||||
const { user_id } = req.query
|
const { user_id: userId } = req.query
|
||||||
if (project_id === '404404404404404404404404') {
|
if (projectId === '404404404404404404404404') {
|
||||||
// not-found
|
// not-found
|
||||||
return res.status(404).send()
|
return res.status(404).send()
|
||||||
}
|
}
|
||||||
if (project_id === '403403403403403403403403') {
|
if (projectId === '403403403403403403403403') {
|
||||||
// forbidden
|
// forbidden
|
||||||
return res.status(403).send()
|
return res.status(403).send()
|
||||||
}
|
}
|
||||||
if (project_id === '429429429429429429429429') {
|
if (projectId === '429429429429429429429429') {
|
||||||
// rate-limited
|
// rate-limited
|
||||||
return res.status(429).send()
|
return res.status(429).send()
|
||||||
} else {
|
} else {
|
||||||
return MockWebServer.joinProject(
|
return MockWebServer.joinProject(
|
||||||
project_id,
|
projectId,
|
||||||
user_id,
|
userId,
|
||||||
(error, project, privilegeLevel) => {
|
(error, project, privilegeLevel) => {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
return next(error)
|
return next(error)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable
|
/* eslint-disable
|
||||||
camelcase,
|
|
||||||
no-return-assign,
|
no-return-assign,
|
||||||
*/
|
*/
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
// TODO: This file was created by bulk-decaffeinate.
|
||||||
|
@ -87,23 +86,23 @@ module.exports = Client = {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
getConnectedClient(client_id, callback) {
|
getConnectedClient(clientId, callback) {
|
||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
callback = function () {}
|
callback = function () {}
|
||||||
}
|
}
|
||||||
return request.get(
|
return request.get(
|
||||||
{
|
{
|
||||||
url: `http://localhost:3026/clients/${client_id}`,
|
url: `http://localhost:3026/clients/${clientId}`,
|
||||||
json: true,
|
json: true,
|
||||||
},
|
},
|
||||||
(error, response, data) => callback(error, data)
|
(error, response, data) => callback(error, data)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
disconnectClient(client_id, callback) {
|
disconnectClient(clientId, callback) {
|
||||||
request.post(
|
request.post(
|
||||||
{
|
{
|
||||||
url: `http://localhost:3026/client/${client_id}/disconnect`,
|
url: `http://localhost:3026/client/${clientId}/disconnect`,
|
||||||
},
|
},
|
||||||
(error, response, data) => callback(error, data)
|
(error, response, data) => callback(error, data)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable
|
/* eslint-disable
|
||||||
camelcase,
|
|
||||||
no-return-assign,
|
no-return-assign,
|
||||||
no-unused-vars,
|
no-unused-vars,
|
||||||
*/
|
*/
|
||||||
|
@ -25,11 +24,11 @@ describe('ConnectedUsersManager', function () {
|
||||||
redis: {
|
redis: {
|
||||||
realtime: {
|
realtime: {
|
||||||
key_schema: {
|
key_schema: {
|
||||||
clientsInProject({ project_id }) {
|
clientsInProject({ project_id: projectId }) {
|
||||||
return `clients_in_project:${project_id}`
|
return `clients_in_project:${projectId}`
|
||||||
},
|
},
|
||||||
connectedUser({ project_id, client_id }) {
|
connectedUser({ project_id: projectId, client_id: clientId }) {
|
||||||
return `connected_user:${project_id}:${client_id}`
|
return `connected_user:${projectId}:${clientId}`
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable
|
/* eslint-disable
|
||||||
camelcase,
|
|
||||||
no-return-assign,
|
no-return-assign,
|
||||||
*/
|
*/
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
// TODO: This file was created by bulk-decaffeinate.
|
||||||
|
@ -32,8 +31,8 @@ describe('DocumentUpdaterController', function () {
|
||||||
redis: {
|
redis: {
|
||||||
documentupdater: {
|
documentupdater: {
|
||||||
key_schema: {
|
key_schema: {
|
||||||
pendingUpdates({ doc_id }) {
|
pendingUpdates({ doc_id: docId }) {
|
||||||
return `PendingUpdates:${doc_id}`
|
return `PendingUpdates:${docId}`
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable
|
/* eslint-disable
|
||||||
camelcase,
|
|
||||||
no-return-assign,
|
no-return-assign,
|
||||||
no-unused-vars,
|
no-unused-vars,
|
||||||
*/
|
*/
|
||||||
|
@ -28,8 +27,8 @@ describe('DocumentUpdaterManager', function () {
|
||||||
redis: {
|
redis: {
|
||||||
documentupdater: {
|
documentupdater: {
|
||||||
key_schema: {
|
key_schema: {
|
||||||
pendingUpdates({ doc_id }) {
|
pendingUpdates({ doc_id: docId }) {
|
||||||
return `PendingUpdates:${doc_id}`
|
return `PendingUpdates:${docId}`
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable
|
/* eslint-disable
|
||||||
camelcase,
|
|
||||||
no-return-assign,
|
no-return-assign,
|
||||||
no-useless-escape,
|
no-useless-escape,
|
||||||
*/
|
*/
|
||||||
|
@ -43,8 +42,8 @@ describe('SafeJsonParse', function () {
|
||||||
|
|
||||||
return it('should return an error on oversized data', function (done) {
|
return it('should return an error on oversized data', function (done) {
|
||||||
// we have a 2k overhead on top of max size
|
// we have a 2k overhead on top of max size
|
||||||
const big_blob = Array(16 * 1024).join('A')
|
const bigBlob = Array(16 * 1024).join('A')
|
||||||
const data = `{\"foo\": \"${big_blob}\"}`
|
const data = `{\"foo\": \"${bigBlob}\"}`
|
||||||
this.Settings.maxUpdateSize = 2 * 1024
|
this.Settings.maxUpdateSize = 2 * 1024
|
||||||
return this.SafeJsonParse.parse(data, (error, parsed) => {
|
return this.SafeJsonParse.parse(data, (error, parsed) => {
|
||||||
this.logger.error.called.should.equal(false)
|
this.logger.error.called.should.equal(false)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable
|
/* eslint-disable
|
||||||
camelcase,
|
|
||||||
no-return-assign,
|
no-return-assign,
|
||||||
no-throw-literal,
|
no-throw-literal,
|
||||||
no-unused-vars,
|
no-unused-vars,
|
||||||
|
@ -317,8 +316,8 @@ describe('WebsocketController', function () {
|
||||||
this.clientsInRoom = []
|
this.clientsInRoom = []
|
||||||
this.io = {
|
this.io = {
|
||||||
sockets: {
|
sockets: {
|
||||||
clients: room_id => {
|
clients: roomId => {
|
||||||
if (room_id !== this.project_id) {
|
if (roomId !== this.project_id) {
|
||||||
throw 'expected room_id to be project_id'
|
throw 'expected room_id to be project_id'
|
||||||
}
|
}
|
||||||
return this.clientsInRoom
|
return this.clientsInRoom
|
||||||
|
@ -396,8 +395,8 @@ describe('WebsocketController', function () {
|
||||||
this.clientsInRoom = ['mock-remaining-client']
|
this.clientsInRoom = ['mock-remaining-client']
|
||||||
this.io = {
|
this.io = {
|
||||||
sockets: {
|
sockets: {
|
||||||
clients: room_id => {
|
clients: roomId => {
|
||||||
if (room_id !== this.project_id) {
|
if (roomId !== this.project_id) {
|
||||||
throw 'expected room_id to be project_id'
|
throw 'expected room_id to be project_id'
|
||||||
}
|
}
|
||||||
return this.clientsInRoom
|
return this.clientsInRoom
|
||||||
|
@ -600,11 +599,11 @@ describe('WebsocketController', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
return it('should call the callback with the escaped lines', function () {
|
return it('should call the callback with the escaped lines', function () {
|
||||||
const escaped_lines = this.callback.args[0][1]
|
const escapedLines = this.callback.args[0][1]
|
||||||
const escaped_word = escaped_lines.pop()
|
const escapedWord = escapedLines.pop()
|
||||||
escaped_word.should.equal('räksmörgås')
|
escapedWord.should.equal('räksmörgås')
|
||||||
// Check that unescaping works
|
// Check that unescaping works
|
||||||
return decodeURIComponent(escape(escaped_word)).should.equal(
|
return decodeURIComponent(escape(escapedWord)).should.equal(
|
||||||
'räksmörgås'
|
'räksmörgås'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -623,10 +622,10 @@ describe('WebsocketController', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
return it('should call the callback with the encoded comment', function () {
|
return it('should call the callback with the encoded comment', function () {
|
||||||
const encoded_comments = this.callback.args[0][4]
|
const encodedComments = this.callback.args[0][4]
|
||||||
const encoded_comment = encoded_comments.comments.pop()
|
const encodedComment = encodedComments.comments.pop()
|
||||||
const encoded_comment_text = encoded_comment.op.c
|
const encodedCommentText = encodedComment.op.c
|
||||||
return encoded_comment_text.should.equal('räksmörgås')
|
return encodedCommentText.should.equal('räksmörgås')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -641,10 +640,10 @@ describe('WebsocketController', function () {
|
||||||
this.callback
|
this.callback
|
||||||
)
|
)
|
||||||
|
|
||||||
const encoded_changes = this.callback.args[0][4]
|
const encodedChanges = this.callback.args[0][4]
|
||||||
const encoded_change = encoded_changes.changes.pop()
|
const encodedChange = encodedChanges.changes.pop()
|
||||||
const encoded_change_text = encoded_change.op.i
|
const encodedChangeText = encodedChange.op.i
|
||||||
return encoded_change_text.should.equal('räksmörgås')
|
return encodedChangeText.should.equal('räksmörgås')
|
||||||
})
|
})
|
||||||
|
|
||||||
return it('should call the callback with the encoded delete change', function () {
|
return it('should call the callback with the encoded delete change', function () {
|
||||||
|
@ -657,10 +656,10 @@ describe('WebsocketController', function () {
|
||||||
this.callback
|
this.callback
|
||||||
)
|
)
|
||||||
|
|
||||||
const encoded_changes = this.callback.args[0][4]
|
const encodedChanges = this.callback.args[0][4]
|
||||||
const encoded_change = encoded_changes.changes.pop()
|
const encodedChange = encodedChanges.changes.pop()
|
||||||
const encoded_change_text = encoded_change.op.d
|
const encodedChangeText = encodedChange.op.d
|
||||||
return encoded_change_text.should.equal('räksmörgås')
|
return encodedChangeText.should.equal('räksmörgås')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -746,11 +745,7 @@ describe('WebsocketController', function () {
|
||||||
this.AuthorizationManager.assertClientCanViewProjectAndDoc.yields(
|
this.AuthorizationManager.assertClientCanViewProjectAndDoc.yields(
|
||||||
new Error()
|
new Error()
|
||||||
)
|
)
|
||||||
this.DocumentUpdaterManager.checkDocument = (
|
this.DocumentUpdaterManager.checkDocument = (projectId, docId, cb) => {
|
||||||
project_id,
|
|
||||||
doc_id,
|
|
||||||
cb
|
|
||||||
) => {
|
|
||||||
this.client.disconnected = true
|
this.client.disconnected = true
|
||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
|
@ -790,11 +785,7 @@ describe('WebsocketController', function () {
|
||||||
this.AuthorizationManager.assertClientCanViewProjectAndDoc.yields(
|
this.AuthorizationManager.assertClientCanViewProjectAndDoc.yields(
|
||||||
new Error()
|
new Error()
|
||||||
)
|
)
|
||||||
this.DocumentUpdaterManager.checkDocument = (
|
this.DocumentUpdaterManager.checkDocument = (projectId, docId, cb) => {
|
||||||
project_id,
|
|
||||||
doc_id,
|
|
||||||
cb
|
|
||||||
) => {
|
|
||||||
this.DocumentUpdaterManager.checkDocument = sinon.stub().yields()
|
this.DocumentUpdaterManager.checkDocument = sinon.stub().yields()
|
||||||
this.WebsocketController.joinDoc(
|
this.WebsocketController.joinDoc(
|
||||||
this.client,
|
this.client,
|
||||||
|
@ -838,11 +829,7 @@ describe('WebsocketController', function () {
|
||||||
this.AuthorizationManager.assertClientCanViewProjectAndDoc.yields(
|
this.AuthorizationManager.assertClientCanViewProjectAndDoc.yields(
|
||||||
new Error()
|
new Error()
|
||||||
)
|
)
|
||||||
this.DocumentUpdaterManager.checkDocument = (
|
this.DocumentUpdaterManager.checkDocument = (projectId, docId, cb) => {
|
||||||
project_id,
|
|
||||||
doc_id,
|
|
||||||
cb
|
|
||||||
) => {
|
|
||||||
this.WebsocketController.leaveDoc(this.client, this.doc_id, () => {})
|
this.WebsocketController.leaveDoc(this.client, this.doc_id, () => {})
|
||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
|
@ -873,7 +860,7 @@ describe('WebsocketController', function () {
|
||||||
|
|
||||||
describe('when the client disconnects while RoomManager.joinDoc is running', function () {
|
describe('when the client disconnects while RoomManager.joinDoc is running', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
this.RoomManager.joinDoc = (client, doc_id, cb) => {
|
this.RoomManager.joinDoc = (client, docId, cb) => {
|
||||||
this.client.disconnected = true
|
this.client.disconnected = true
|
||||||
return cb()
|
return cb()
|
||||||
}
|
}
|
||||||
|
@ -909,8 +896,8 @@ describe('WebsocketController', function () {
|
||||||
return describe('when the client disconnects while DocumentUpdaterManager.getDocument is running', function () {
|
return describe('when the client disconnects while DocumentUpdaterManager.getDocument is running', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
this.DocumentUpdaterManager.getDocument = (
|
this.DocumentUpdaterManager.getDocument = (
|
||||||
project_id,
|
projectId,
|
||||||
doc_id,
|
docId,
|
||||||
fromVersion,
|
fromVersion,
|
||||||
callback
|
callback
|
||||||
) => {
|
) => {
|
||||||
|
@ -1524,9 +1511,9 @@ describe('WebsocketController', function () {
|
||||||
this.logger.warn.called.should.equal(true)
|
this.logger.warn.called.should.equal(true)
|
||||||
return this.logger.warn.args[0].should.deep.equal([
|
return this.logger.warn.args[0].should.deep.equal([
|
||||||
{
|
{
|
||||||
user_id: this.user_id,
|
userId: this.user_id,
|
||||||
project_id: this.project_id,
|
projectId: this.project_id,
|
||||||
doc_id: this.doc_id,
|
docId: this.doc_id,
|
||||||
updateSize: 7372835,
|
updateSize: 7372835,
|
||||||
},
|
},
|
||||||
'update is too large',
|
'update is too large',
|
||||||
|
|
Loading…
Reference in a new issue