From 02c2e88a3e9b2acf1dd892651e925ce22b58ba81 Mon Sep 17 00:00:00 2001 From: Mark Haines Date: Tue, 21 Jul 2015 17:39:11 +0100 Subject: [PATCH] Fix some of the lint warnings --- lib/client.js | 129 ++++++++++++++---------- lib/store/session/webstorage.js | 13 +-- spec/integ/matrix-client-crypto.spec.js | 36 +++---- 3 files changed, 104 insertions(+), 74 deletions(-) diff --git a/lib/client.js b/lib/client.js index de6c8c51e..3d219ce16 100644 --- a/lib/client.js +++ b/lib/client.js @@ -63,7 +63,7 @@ function MatrixClient(opts) { var e2eAccount = this.sessionStore.getEndToEndAccount(); var account = new Olm.Account(); try { - if (e2eAccount == null) { + if (e2eAccount === null) { account.create(); } else { account.unpickle(this.accountKey, e2eAccount); @@ -85,7 +85,7 @@ function MatrixClient(opts) { signatures[opts.userId] = {}; signatures[opts.userId]["ed25519:" + this.deviceId] = signature; this.deviceKeys.signatures = signatures; - this.deviceCurve25519Key = e2eKeys["curve25519"]; + this.deviceCurve25519Key = e2eKeys.curve25519; var pickled = account.pickle(this.accountKey); this.sessionStore.storeEndToEndAccount(pickled); var myDevices = this.sessionStore.getEndToEndDevicesForUser( @@ -140,10 +140,12 @@ function MatrixClient(opts) { } utils.inherits(MatrixClient, EventEmitter); - /** * Upload the device keys to the homeserver and ensure that the * homeserver has enough one-time keys. + * @param {number} maxKeys The maximum number of keys to generate + * @param {object} deferred A deferred to resolve when the keys are uploaded. + * @return {object} A promise that will resolve when the keys are uploaded. */ MatrixClient.prototype.uploadKeys = function(maxKeys, deferred) { var first_time = deferred === undefined; @@ -154,9 +156,10 @@ MatrixClient.prototype.uploadKeys = function(maxKeys, deferred) { throw new Error("End-to-end account not found"); } var account = new Olm.Account(); + var oneTimeKeys; try { account.unpickle(this.accountKey, pickled); - var oneTimeKeys = JSON.parse(account.one_time_keys()); + oneTimeKeys = JSON.parse(account.one_time_keys()); var maxOneTimeKeys = account.max_number_of_one_time_keys(); } finally { account.free(); @@ -164,7 +167,9 @@ MatrixClient.prototype.uploadKeys = function(maxKeys, deferred) { var oneTimeJson = {}; for (var keyId in oneTimeKeys.curve25519) { - oneTimeJson["curve25519:" + keyId] = oneTimeKeys.curve25519[keyId]; + if (oneTimeKeys.curve25519.hasOwnProperty(keyId)) { + oneTimeJson["curve25519:" + keyId] = oneTimeKeys.curve25519[keyId]; + } } var content = { device_keys: this.deviceKeys, @@ -204,6 +209,13 @@ MatrixClient.prototype.uploadKeys = function(maxKeys, deferred) { return deferred.promise; }; +/** + * Download the keys for a list of users and stores the keys in the session + * store. + * @param {Array} userIds The users to fetch. + * @param {bool} forceDownload Always download the keys even if cached. + * @return {object} A promise that will resolve when the keys are downloadded. + */ MatrixClient.prototype.downloadKeys = function(userIds, forceDownload) { var stored = {}; var notStored = {}; @@ -250,6 +262,7 @@ MatrixClient.prototype.downloadKeys = function(userIds, forceDownload) { * Enable end-to-end encryption for a room. * @param {string} roomId The room ID to enable encryption in. * @param {object} config The encryption config for the room. + * @return {Object} A promise that will resolve when encryption is setup. */ MatrixClient.prototype.setRoomEncryption = function(roomId, config) { if (config.algorithm === OLM_ALGORITHM) { @@ -267,13 +280,15 @@ MatrixClient.prototype.setRoomEncryption = function(roomId, config) { userWithoutDevices.push(userId); } else { for (var deviceId in devices) { - var keys = devices[deviceId]; - var key = keys.keys["curve25519:" + deviceId]; - if (key == this.deviceCurve25519Key) { - continue; - } - if (!this.sessionStore.getEndToEndSessions(key)) { - devicesWithoutSession.push([userId, deviceId, key]); + if (devices.hasOwnProperty(deviceId)) { + var keys = devices[deviceId]; + var key = keys.keys["curve25519:" + deviceId]; + if (key == this.deviceCurve25519Key) { + continue; + } + if (!this.sessionStore.getEndToEndSessions(key)) { + devicesWithoutSession.push([userId, deviceId, key]); + } } } } @@ -281,7 +296,7 @@ MatrixClient.prototype.setRoomEncryption = function(roomId, config) { var deferred = q.defer(); if (devicesWithoutSession.length > 0) { var queries = {}; - for (var i = 0; i < devicesWithoutSession.length; ++i) { + for (i = 0; i < devicesWithoutSession.length; ++i) { var device = devicesWithoutSession[i]; var query = queries[device[0]] || {}; queries[device[0]] = query; @@ -295,13 +310,13 @@ MatrixClient.prototype.setRoomEncryption = function(roomId, config) { httpApi.PREFIX_V2_ALPHA ).then(function(res) { var missing = {}; - for (var i = 0; i < devicesWithoutSession.length; ++i) { + for (i = 0; i < devicesWithoutSession.length; ++i) { var device = devicesWithoutSession[i]; var userRes = res.one_time_keys[device[0]] || {}; var deviceRes = userRes[device[1]]; var oneTimeKey; for (var keyId in deviceRes) { - if (keyId.indexOf("curve25519:") == 0) { + if (keyId.indexOf("curve25519:") === 0) { oneTimeKey = deviceRes[keyId]; } } @@ -313,7 +328,7 @@ MatrixClient.prototype.setRoomEncryption = function(roomId, config) { account.unpickle(self.accountKey, pickled); session.create_outbound(account, device[2], oneTimeKey); var sessionId = session.session_id(); - var pickled = session.pickle(self.accountKey); + pickled = session.pickle(self.accountKey); self.sessionStore.storeEndToEndSession( device[2], sessionId, pickled ); @@ -328,13 +343,13 @@ MatrixClient.prototype.setRoomEncryption = function(roomId, config) { } deferred.resolve({ missingUsers: userWithoutDevices, - missingDevices: missing, + missingDevices: missing }); }); } else { deferred.resolve({ missingUsers: userWithoutDevices, - missingDevices: [], + missingDevices: [] }); } this.sessionStore.storeEndToEndRoom(roomId, config); @@ -344,6 +359,11 @@ MatrixClient.prototype.setRoomEncryption = function(roomId, config) { } }; + +/** + * Disable encryption for a room. + * @param {string} roomId the room to disable encryption for. + */ MatrixClient.prototype.disableRoomEncryption = function(roomId) { this.sessionStore.storeEndToEndRoom(roomId, null); }; @@ -604,13 +624,14 @@ function _encryptMessage(client, roomId, e2eRoomInfo, eventType, content, var participantKeys = []; for (var i = 0; i < e2eRoomInfo.members.length; ++i) { var userId = e2eRoomInfo.members[i]; - var userCiphertext = {}; var devices = client.sessionStore.getEndToEndDevicesForUser(userId); for (var deviceId in devices) { + if (devices.hasOwnProperty(deviceId)) { var keys = devices[deviceId]; - for (var keyId in keys.keys) { - if (keyId.indexOf("curve25519:") == 0) { - participantKeys.push(keys.keys[keyId]); + for (var keyId in keys.keys) { + if (keyId.indexOf("curve25519:") === 0) { + participantKeys.push(keys.keys[keyId]); + } } } } @@ -626,7 +647,7 @@ function _encryptMessage(client, roomId, e2eRoomInfo, eventType, content, }; var ciphertext = {}; var payloadString = JSON.stringify(payloadJson); - for (var i = 0; i < participantKeys.length; ++i) { + for (i = 0; i < participantKeys.length; ++i) { var deviceKey = participantKeys[i]; if (deviceKey == client.deviceCurve25519Key) { continue; @@ -635,17 +656,19 @@ function _encryptMessage(client, roomId, e2eRoomInfo, eventType, content, deviceKey ); var sessionIds = []; - for (sessionId in sessions) { - sessionIds.push(sessionId); + for (var sessionId in sessions) { + if (sessions.hasOwnProperty(sessionId)) { + sessionIds.push(sessionId); + } } // Use the session with the lowest ID. - sessionIds.sort() - if (sessionIds.length == 0) { + sessionIds.sort(); + if (sessionIds.length === 0) { // If we don't have a session for a device then // we can't encrypt a message for it. continue; } - var sessionId = sessionIds[0]; + sessionId = sessionIds[0]; var session = new Olm.Session(); try { session.unpickle(client.accountKey, sessions[sessionId]); @@ -678,7 +701,6 @@ function _decryptMessage(client, event) { var content = event.getContent(); if (content.algorithm === OLM_ALGORITHM) { - var sender = event.getSender(); var deviceKey = content.sender_key; var ciphertext = content.ciphertext; @@ -692,29 +714,34 @@ function _decryptMessage(client, event) { var sessions = client.sessionStore.getEndToEndSessions(deviceKey); var payloadString = null; var foundSession = false; - for (sessionId in sessions) { - var session = new Olm.Session(); - try { - session.unpickle(client.accountKey, sessions[sessionId]); - if (message.type == 0 && session.matches_inbound(message.body)) { - foundSession = true; + var session; + for (var sessionId in sessions) { + if (sessions.hasOwnProperty(sessionId)) { + session = new Olm.Session(); + try { + session.unpickle(client.accountKey, sessions[sessionId]); + if (message.type === 0 && session.matches_inbound(message.body)) { + foundSession = true; + } + payloadString = session.decrypt(message.type, message.body); + var pickled = session.pickle(client.accountKey); + client.sessionStore.storeEndToEndSession( + deviceKey, sessionId, pickled + ); + } catch (e) { + // Failed to decrypt with an existing session. + console.log( + "Failed to decrypt with an existing session: " + e.message + ); + } finally { + session.free(); } - payloadString = session.decrypt(message.type, message.body); - var pickled = session.pickle(client.accountKey); - client.sessionStore.storeEndToEndSession( - deviceKey, sessionId, pickled - ); - } catch(e) { - // Failed to decrypt with an existing session. - console.log("Failed to decrypt with an existing session: " + e.message); - } finally { - session.free(); } } - if (message.type == 0 && !foundSession && payloadString === null) { + if (message.type === 0 && !foundSession && payloadString === null) { var account = new Olm.Account(); - var session = new Olm.Session(); + session = new Olm.Session(); try { var account_data = client.sessionStore.getEndToEndAccount(); account.unpickle(client.accountKey, account_data); @@ -723,12 +750,12 @@ function _decryptMessage(client, event) { account.remove_one_time_keys(session); var pickledSession = session.pickle(client.accountKey); var pickledAccount = account.pickle(client.accountKey); - var sessionId = session.session_id(); + sessionId = session.session_id(); client.sessionStore.storeEndToEndSession( deviceKey, sessionId, pickledSession ); client.sessionStore.storeEndToEndAccount(pickledAccount); - } catch(e) { + } catch (e) { // Failed to decrypt with a new session. } finally { session.free(); @@ -746,7 +773,7 @@ function _decryptMessage(client, event) { user_id: event.getSender(), event_id: event.getId(), type: payload.type, - content: payload.content, + content: payload.content }); } else { return _badEncryptedMessage(event, "Bad Encrypted Message"); @@ -2134,7 +2161,7 @@ function _resolve(callback, defer, res) { } function _PojoToMatrixEventMapper(client) { - function mapper (plainOldJsObject) { + function mapper(plainOldJsObject) { var event = new MatrixEvent(plainOldJsObject); if (event.getType() === "m.room.encrypted") { return _decryptMessage(client, event); diff --git a/lib/store/session/webstorage.js b/lib/store/session/webstorage.js index 165297151..f983d86e2 100644 --- a/lib/store/session/webstorage.js +++ b/lib/store/session/webstorage.js @@ -16,9 +16,9 @@ var E2E_PREFIX = "session.e2e."; */ function WebStorageSessionStore(webStore) { this.store = webStore; - if (!utils.isFunction(webStore.getItem) - || !utils.isFunction(webStore.setItem) - || !utils.isFunction(webStore.removeItem)) { + if (!utils.isFunction(webStore.getItem) || + !utils.isFunction(webStore.setItem) || + !utils.isFunction(webStore.removeItem)) { throw new Error( "Supplied webStore does not meet the WebStorage API interface" ); @@ -48,7 +48,7 @@ WebStorageSessionStore.prototype = { * @param {string} userId The user's ID. * @param {object} devices A map from device ID to keys for the device. */ - storeEndToEndDevicesForUser : function(userId, devices) { + storeEndToEndDevicesForUser: function(userId, devices) { setJsonItem(this.store, keyEndToEndDevicesForUser(userId), devices); }, @@ -58,7 +58,7 @@ WebStorageSessionStore.prototype = { * @return {object} A map from device ID to keys for the device. */ getEndToEndDevicesForUser: function(userId) { - return getJsonItem(this.store, keyEndToEndDevicesForUser(userId)) + return getJsonItem(this.store, keyEndToEndDevicesForUser(userId)); }, /** @@ -102,7 +102,7 @@ WebStorageSessionStore.prototype = { getEndToEndRoom: function(roomId) { return getJsonItem(this.store, keyEndToEndRoom(roomId)); } -} +}; var KEY_END_TO_END_ACCOUNT = E2E_PREFIX + "account"; @@ -139,4 +139,5 @@ function debuglog() { } } +/** */ module.exports = WebStorageSessionStore; diff --git a/spec/integ/matrix-client-crypto.spec.js b/spec/integ/matrix-client-crypto.spec.js index 79465801c..8b7aeda3e 100644 --- a/spec/integ/matrix-client-crypto.spec.js +++ b/spec/integ/matrix-client-crypto.spec.js @@ -23,11 +23,11 @@ describe("MatrixClient crypto", function() { var aliClient; var roomId = "!room:localhost"; var aliUserId = "@ali:localhost"; - var aliDeviceId = "zxcvb" + var aliDeviceId = "zxcvb"; var aliAccessToken = "aseukfgwef"; - var bobClient, httpBackend; + var bobClient; var bobUserId = "@bob:localhost"; - var bobDeviceId = "bvcxz" + var bobDeviceId = "bvcxz"; var bobAccessToken = "fewgfkuesa"; var bobOneTimeKeys; var bobDeviceKeys; @@ -50,7 +50,7 @@ describe("MatrixClient crypto", function() { userId: aliUserId, accessToken: aliAccessToken, deviceId: aliDeviceId, - sessionStore: aliStorage, + sessionStore: aliStorage }); bobClient = sdk.createClient({ @@ -58,7 +58,7 @@ describe("MatrixClient crypto", function() { userId: bobUserId, accessToken: bobAccessToken, deviceId: bobDeviceId, - sessionStore: bobStorage, + sessionStore: bobStorage }); httpBackend.when("GET", "/pushrules").respond(200, {}); @@ -78,15 +78,18 @@ describe("MatrixClient crypto", function() { }); function bobUploadsKeys(done) { - httpBackend.when("POST", "/keys/upload/bvcxz").respond(200, function(path, content) { + var uploadPath = "/keys/upload/bvcxz"; + httpBackend.when("POST", uploadPath).respond(200, function(path, content) { expect(content.one_time_keys).toEqual({}); - httpBackend.when("POST", "/keys/upload/bvcxz").respond(200, function(path, content) { + httpBackend.when("POST", uploadPath).respond(200, function(path, content) { expect(content.one_time_keys).not.toEqual({}); bobDeviceKeys = content.device_keys; bobOneTimeKeys = content.one_time_keys; - var count = 0; + var count = 0; for (var key in content.one_time_keys) { - count++; + if (content.one_time_keys.hasOwnProperty(key)) { + count++; + } } expect(count).toEqual(5); return {one_time_key_counts: {curve25519: count}}; @@ -102,7 +105,7 @@ describe("MatrixClient crypto", function() { }); } - it("Bob should upload without one-time keys and then again with one-time keys", bobUploadsKeys); + it("Bob uploads without one-time keys and with one-time keys", bobUploadsKeys); function aliDownloadsKeys(done) { var bobKeys = {}; @@ -129,8 +132,10 @@ describe("MatrixClient crypto", function() { httpBackend.when("POST", "/keys/claim").respond(200, function(path, content) { expect(content.one_time_keys[bobUserId][bobDeviceId]).toEqual("curve25519"); for (var keyId in bobOneTimeKeys) { - if (keyId.indexOf("curve25519:") == 0) { - break; + if (bobOneTimeKeys.hasOwnProperty(keyId)) { + if (keyId.indexOf("curve25519:") === 0) { + break; + } } } var result = {}; @@ -159,7 +164,7 @@ describe("MatrixClient crypto", function() { }); function aliSendsMessage(done) { - var txnId = "a.transaction.id" + var txnId = "a.transaction.id"; var path = "/send/m.room.encrypted/" + txnId; httpBackend.when("PUT", path).respond(200, function(path, content) { aliMessage = content; @@ -169,7 +174,7 @@ describe("MatrixClient crypto", function() { aliClient.sendMessage( roomId, {msgtype: "m.text", body: "Hello, World"}, txnId ); - httpBackend.flush().done(function() {done()}); + httpBackend.flush().done(function() {done();}); } it("Ali sends a message", function(done) { @@ -222,7 +227,4 @@ describe("MatrixClient crypto", function() { }); }, 30000); //timeout after 30s - - - });