From 5e0b04965478cf74b6e45cf2872e8eb2f50a00ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20HUBSCHER?= Date: Thu, 21 Apr 2016 16:24:20 +0200 Subject: [PATCH] Refresh the sessionId if the apiKey changed in the config. --- LICENSE | 2 +- loop/routes/rooms.js | 171 ++++++++++++++++++++++++------------------- test/rooms_test.js | 35 +++++++++ 3 files changed, 133 insertions(+), 75 deletions(-) diff --git a/LICENSE b/LICENSE index 52d1351..2f8ed18 100644 --- a/LICENSE +++ b/LICENSE @@ -35,7 +35,7 @@ Mozilla Public License Version 2.0 means any form of the work other than Source Code Form. 1.7. "Larger Work" - means a work that combines Covered Software with other material, in + means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. 1.8. "License" diff --git a/loop/routes/rooms.js b/loop/routes/rooms.js index 1455567..94b675e 100644 --- a/loop/routes/rooms.js +++ b/loop/routes/rooms.js @@ -371,91 +371,114 @@ module.exports = function (apiRouter, conf, logError, storage, filestorage, auth return; } var channel = req.roomStorageData.channel; - var ttl = roomsConf.participantTTL; - var role = req.user === roomOwnerHmac ? 'moderator' : 'publisher'; - var sessionToken = tokBox.getSessionToken( - req.roomStorageData.sessionId, - role, - channel - ); - req.roomStorageData.sessionToken = sessionToken; - - function next(err) { - if (res.serverError(err)) return; - storage.getRoomParticipants(req.token, function(err, - participants) { + + // Look in the config for the current apiKey for this channel + if (tokBox.credentials[channel].apiKey !== req.roomStorageData.apiKey) { + // If the apiKey stored in the roomStorageData is not the same as in the config + // Ask for a new sessionId and store it in the roomStorageData. + tokBox.getSession({channel: channel}, + function(err, session, opentok) { if (res.serverError(err)) return; - // When talking about room participants, we are - // talking about user devices present in the room. + req.roomStorageData.sessionId = session.sessionId; + req.roomStorageData.apiKey = opentok.apiKey; - // In case we are rejoining, we don't want to - // consider this session to already be in the - // room. The otherParticipants filters this - // session device from the participant list so - // that we can rejoin even if we are already - // supposed to be in the roon. + storage.setUserRoomData(req.user, req.token, + req.roomStorageData, renderRoomInformation); + }); + } else { + renderRoomInformation(); + } - var otherParticipants = participants.filter(function(participant) { - return req.user === undefined || participant.userMac !== req.user; - }); + function renderRoomInformation(err) { + if (res.serverError(err)) return; - // Room participants are used by metrics - req.roomParticipantsCount = participants.length; - - var roomMaxSize = req.roomStorageData.maxSize; - if (!canJoinRoom( - otherParticipants, roomMaxSize, - req.roomStorageData.roomOwnerHmac, - req.user)) { - sendError(res, 400, errors.ROOM_FULL, "The room is full."); - return; - } else if (requestMaxSize <= otherParticipants.length) { - // You cannot handle the number of actual participants. - sendError(res, 400, errors.CLIENT_REACHED_CAPACITY, - "Too many participants in the room for you to handle."); - return; - } - - getUserAccount(storage, req, function(err, acc) { + var ttl = roomsConf.participantTTL; + var role = req.user === roomOwnerHmac ? 'moderator' : 'publisher'; + var sessionToken = tokBox.getSessionToken( + req.roomStorageData.sessionId, + role, + channel + ); + req.roomStorageData.sessionToken = sessionToken; + + function next(err) { + if (res.serverError(err)) return; + storage.getRoomParticipants(req.token, function(err, + participants) { if (res.serverError(err)) return; - encryptAccountName(req.token, acc, function(account) { - req.roomConnectionId = uuid.v4(); - storage.addRoomParticipant(req.token, participantHmac, { - id: req.roomConnectionId, - displayName: req.body.displayName, - clientMaxSize: requestMaxSize, - userMac: req.user, - account: account - }, ttl, function(err) { - if (res.serverError(err)) return; - - // A participant was just added. - req.roomParticipantsCount++; - - emitRoomEvent(req.token, + + // When talking about room participants, we are + // talking about user devices present in the room. + + // In case we are rejoining, we don't want to + // consider this session to already be in the + // room. The otherParticipants filters this + // session device from the participant list so + // that we can rejoin even if we are already + // supposed to be in the roon. + + var otherParticipants = participants.filter(function(participant) { + return req.user === undefined || participant.userMac !== req.user; + }); + + // Room participants are used by metrics + req.roomParticipantsCount = participants.length; + + var roomMaxSize = req.roomStorageData.maxSize; + if (!canJoinRoom( + otherParticipants, roomMaxSize, req.roomStorageData.roomOwnerHmac, - "join", - function(err) { - if (res.serverError(err)) return; - res.status(200).json({ - apiKey: req.roomStorageData.apiKey, - sessionId: req.roomStorageData.sessionId, - sessionToken: sessionToken, - expires: ttl + req.user)) { + sendError(res, 400, errors.ROOM_FULL, "The room is full."); + return; + } else if (requestMaxSize <= otherParticipants.length) { + // You cannot handle the number of actual participants. + sendError(res, 400, errors.CLIENT_REACHED_CAPACITY, + "Too many participants in the room for you to handle."); + return; + } + + getUserAccount(storage, req, function(err, acc) { + if (res.serverError(err)) return; + encryptAccountName(req.token, acc, function(account) { + req.roomConnectionId = uuid.v4(); + storage.addRoomParticipant(req.token, participantHmac, { + id: req.roomConnectionId, + displayName: req.body.displayName, + clientMaxSize: requestMaxSize, + userMac: req.user, + account: account + }, ttl, function(err) { + if (res.serverError(err)) return; + + // A participant was just added. + req.roomParticipantsCount++; + + emitRoomEvent(req.token, + req.roomStorageData.roomOwnerHmac, + "join", + function(err) { + if (res.serverError(err)) return; + res.status(200).json({ + apiKey: req.roomStorageData.apiKey, + sessionId: req.roomStorageData.sessionId, + sessionToken: sessionToken, + expires: ttl + }); }); - }); + }); }); }); - }); - }); - } - if (participantHmac === undefined) { - participantHmac = hmac(sessionToken, conf.get('userMacSecret')); - storage.setRoomAccessToken(req.token, participantHmac, ttl, next); - return; + }); + } + if (participantHmac === undefined) { + participantHmac = hmac(sessionToken, conf.get('userMacSecret')); + storage.setRoomAccessToken(req.token, participantHmac, ttl, next); + return; + } + next(); } - next(); }); }, handleRefresh: function(req, res) { diff --git a/test/rooms_test.js b/test/rooms_test.js index 57bcc7f..3ce4a53 100644 --- a/test/rooms_test.js +++ b/test/rooms_test.js @@ -1640,6 +1640,41 @@ describe("/rooms", function() { }); }); }); + + it("should refresh the sessionId in case it is obsolete.", function(done) { + createRoom(hawkCredentials).end(function(err, res) { + if (err) throw err; + var roomToken = res.body.roomToken; + + storage.getRoomData(roomToken, function(err, roomData) { + if (err) throw err; + // Update apiKey with other credentials + roomData.apiKey = "old api key"; + roomData.sessionId = "old sessionId"; + storage.setUserRoomData(userHmac, roomToken, roomData, function(err) { + if (err) throw err; + joinRoom(hawkCredentials, roomToken, { + action: "join", + clientMaxSize: 10, + displayName: "Natim" + }).end(function(err, res) { + if (err) throw err; + expect(res.body).to.eql({ + "apiKey": tokBox._opentok.default.apiKey, + "expires": conf.get("rooms").participantTTL, + "sessionId": sessionId, + "sessionToken": sessionToken + }); + storage.getRoomParticipants(roomToken, function(err, participants) { + if (err) throw err; + expect(participants).to.length(1); + done(); + }); + }); + }); + }); + }); + }); }); describe("Handle 'refresh'", function() {