mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Add in /clients and /client/:client_id status end points
This commit is contained in:
parent
8b923d2fda
commit
0b18edeff3
9 changed files with 122 additions and 6 deletions
37
services/real-time/app/coffee/HttpController.coffee
Normal file
37
services/real-time/app/coffee/HttpController.coffee
Normal file
|
@ -0,0 +1,37 @@
|
|||
Utils = require "./Utils"
|
||||
async = require "async"
|
||||
|
||||
module.exports = HttpController =
|
||||
# The code in this controller is hard to unit test because of a lot of
|
||||
# dependencies on internal socket.io methods. It is not critical to the running
|
||||
# of ShareLaTeX, and is only used for getting stats about connected clients,
|
||||
# and for checking internal state in acceptance tests. The acceptances tests
|
||||
# should provide appropriate coverage.
|
||||
_getConnectedClientView: (ioClient, callback = (error, client) ->) ->
|
||||
client_id = ioClient.id
|
||||
Utils.getClientAttributes ioClient, [
|
||||
"project_id", "user_id", "first_name", "last_name", "email", "connected_time"
|
||||
], (error, {project_id, user_id, first_name, last_name, email, connected_time}) ->
|
||||
return callback(error) if error?
|
||||
client = {client_id, project_id, user_id, first_name, last_name, email, connected_time}
|
||||
client.rooms = []
|
||||
for name, joined of ioClient.manager.roomClients[client_id]
|
||||
if joined and name != ""
|
||||
client.rooms.push name.replace(/^\//, "") # Remove leading /
|
||||
callback(null, client)
|
||||
|
||||
getConnectedClients: (req, res, next) ->
|
||||
io = req.app.get("io")
|
||||
ioClients = io.sockets.clients()
|
||||
async.map ioClients, HttpController._getConnectedClientView, (error, clients) ->
|
||||
return next(error) if error?
|
||||
res.json clients
|
||||
|
||||
getConnectedClient: (req, res, next) ->
|
||||
{client_id} = req.params
|
||||
io = req.app.get("io")
|
||||
ioClient = io.sockets.socket(client_id)
|
||||
HttpController._getConnectedClientView ioClient, (error, client) ->
|
||||
return next(error) if error?
|
||||
res.json client
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
Metrics = require "metrics-sharelatex"
|
||||
logger = require "logger-sharelatex"
|
||||
WebsocketController = require "./WebsocketController"
|
||||
HttpController = require "./HttpController"
|
||||
|
||||
module.exports = Router =
|
||||
# We don't want to send raw errors back to the client, in case they
|
||||
|
@ -71,4 +72,8 @@ module.exports = Router =
|
|||
# Don't return raw error to prevent leaking server side info
|
||||
return callback {message: "Something went wrong"}
|
||||
else
|
||||
callback(null, args...)
|
||||
callback(null, args...)
|
||||
|
||||
app.set("io", io)
|
||||
app.get "/clients", HttpController.getConnectedClients
|
||||
app.get "/clients/:client_id", HttpController.getConnectedClient
|
14
services/real-time/app/coffee/Utils.coffee
Normal file
14
services/real-time/app/coffee/Utils.coffee
Normal file
|
@ -0,0 +1,14 @@
|
|||
async = require "async"
|
||||
|
||||
module.exports = Utils =
|
||||
getClientAttributes: (client, keys, callback = (error, attributes) ->) ->
|
||||
attributes = {}
|
||||
jobs = keys.map (key) ->
|
||||
(callback) ->
|
||||
client.get key, (error, value) ->
|
||||
return callback(error) if error?
|
||||
attributes[key] = value
|
||||
callback()
|
||||
async.series jobs, (error) ->
|
||||
return callback(error) if error?
|
||||
callback null, attributes
|
|
@ -19,6 +19,8 @@ module.exports = WebsocketController =
|
|||
err = new Error("not authorized")
|
||||
logger.error {err, project_id, user_id, client_id: client.id}, "user is not authorized to join project"
|
||||
return callback(err)
|
||||
|
||||
client.join project_id
|
||||
|
||||
client.set("privilege_level", privilegeLevel)
|
||||
client.set("user_id", user_id)
|
||||
|
@ -67,5 +69,4 @@ module.exports = WebsocketController =
|
|||
_getClientData: (client, callback = (error, data) ->) ->
|
||||
client.get "user_id", (error, user_id) ->
|
||||
client.get "project_id", (error, project_id) ->
|
||||
callback null, {client_id: client.id, project_id, user_id}
|
||||
|
||||
callback null, {client_id: client.id, project_id, user_id}
|
|
@ -8,6 +8,7 @@
|
|||
"url": "https://github.com/sharelatex/real-time-sharelatex.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "^0.9.0",
|
||||
"connect-redis": "^2.1.0",
|
||||
"express": "^4.10.1",
|
||||
"express-session": "^1.9.1",
|
||||
|
|
|
@ -41,6 +41,11 @@ describe "joinProject", ->
|
|||
it "should return the protocolVersion", ->
|
||||
@protocolVersion.should.equal 2
|
||||
|
||||
it "should have joined the project room", (done) ->
|
||||
RealTimeClient.getConnectedClient @client.socket.sessionid, (error, client) =>
|
||||
expect(@project_id in client.rooms).to.equal true
|
||||
done()
|
||||
|
||||
describe "when not authorized", ->
|
||||
before (done) ->
|
||||
FixturesManager.setUpProject {
|
||||
|
@ -60,3 +65,8 @@ describe "joinProject", ->
|
|||
it "should return an error", ->
|
||||
# We don't return specific errors
|
||||
@error.message.should.equal "Something went wrong"
|
||||
|
||||
it "should not have joined the project room", (done) ->
|
||||
RealTimeClient.getConnectedClient @client.socket.sessionid, (error, client) =>
|
||||
expect(@project_id in client.rooms).to.equal false
|
||||
done()
|
||||
|
|
|
@ -5,7 +5,7 @@ RealTimeClient = require "./helpers/RealTimeClient"
|
|||
|
||||
describe "Session", ->
|
||||
describe "with an established session", ->
|
||||
beforeEach (done) ->
|
||||
before (done) ->
|
||||
@user_id = "mock-user-id"
|
||||
RealTimeClient.setSession {
|
||||
user: { _id: @user_id }
|
||||
|
@ -22,9 +22,19 @@ describe "Session", ->
|
|||
expect(disconnected).to.equal false
|
||||
done()
|
||||
, 500
|
||||
|
||||
it "should appear in the list of connected clients", (done) ->
|
||||
RealTimeClient.getConnectedClients (error, clients) =>
|
||||
included = false
|
||||
for client in clients
|
||||
if client.client_id == @client.socket.sessionid
|
||||
included = true
|
||||
break
|
||||
expect(included).to.equal true
|
||||
done()
|
||||
|
||||
describe "without an established session", ->
|
||||
beforeEach (done) ->
|
||||
before (done) ->
|
||||
RealTimeClient.unsetSession (error) =>
|
||||
throw error if error?
|
||||
@client = RealTimeClient.connect()
|
||||
|
@ -34,8 +44,18 @@ describe "Session", ->
|
|||
@client.on "disconnect", () ->
|
||||
done()
|
||||
|
||||
it "not should appear in the list of connected clients", (done) ->
|
||||
RealTimeClient.getConnectedClients (error, clients) =>
|
||||
included = false
|
||||
for client in clients
|
||||
if client.client_id == @client.socket.sessionid
|
||||
included = true
|
||||
break
|
||||
expect(included).to.equal false
|
||||
done()
|
||||
|
||||
describe "without a valid user set on the session", ->
|
||||
beforeEach (done) ->
|
||||
before (done) ->
|
||||
RealTimeClient.setSession {
|
||||
foo: "bar"
|
||||
}, (error) =>
|
||||
|
@ -45,4 +65,14 @@ describe "Session", ->
|
|||
|
||||
it "should get disconnected", (done) ->
|
||||
@client.on "disconnect", () ->
|
||||
done()
|
||||
|
||||
it "not should appear in the list of connected clients", (done) ->
|
||||
RealTimeClient.getConnectedClients (error, clients) =>
|
||||
included = false
|
||||
for client in clients
|
||||
if client.client_id == @client.socket.sessionid
|
||||
included = true
|
||||
break
|
||||
expect(included).to.equal false
|
||||
done()
|
|
@ -1,6 +1,7 @@
|
|||
XMLHttpRequest = require("../../libs/XMLHttpRequest").XMLHttpRequest
|
||||
io = require("socket.io-client")
|
||||
|
||||
request = require "request"
|
||||
Settings = require "settings-sharelatex"
|
||||
redis = require "redis-sharelatex"
|
||||
rclient = redis.createClient(Settings.redis.web)
|
||||
|
@ -37,4 +38,18 @@ module.exports = Client =
|
|||
connect: (cookie) ->
|
||||
client = io.connect("http://localhost:3026", 'force new connection': true)
|
||||
return client
|
||||
|
||||
getConnectedClients: (callback = (error, clients) ->) ->
|
||||
request.get {
|
||||
url: "http://localhost:3026/clients"
|
||||
json: true
|
||||
}, (error, response, data) ->
|
||||
callback error, data
|
||||
|
||||
getConnectedClient: (client_id, callback = (error, clients) ->) ->
|
||||
request.get {
|
||||
url: "http://localhost:3026/clients/#{client_id}"
|
||||
json: true
|
||||
}, (error, response, data) ->
|
||||
callback error, data
|
||||
|
||||
|
|
|
@ -51,6 +51,9 @@ describe 'WebsocketController', ->
|
|||
.calledWith(@project_id, @user._id)
|
||||
.should.equal true
|
||||
|
||||
it "should join the project room", ->
|
||||
@client.join.calledWith(@project_id).should.equal true
|
||||
|
||||
it "should set the privilege level on the client", ->
|
||||
@client.set.calledWith("privilege_level", @privilegeLevel).should.equal true
|
||||
|
||||
|
|
Loading…
Reference in a new issue