Ver Fonte

Add own device to the server-stored devicelist

updates #497
JC Brand há 7 anos atrás
pai
commit
9645641505
4 ficheiros alterados com 100 adições e 44 exclusões
  1. 25 32
      spec/omemo.js
  2. 5 5
      spec/presence.js
  3. 37 6
      src/converse-omemo.js
  4. 33 1
      tests/mock.js

+ 25 - 32
spec/omemo.js

@@ -6,38 +6,6 @@
     var $iq = converse.env.$iq;
     var _ = converse.env._;
 
-    window.libsignal = {
-        'KeyHelper': {
-            'generateIdentityKeyPair': function () {
-                return Promise.resolve({
-                    'pubKey': 1234,
-                    'privKey': 4321
-                });
-            },
-            'generateRegistrationId': function () {
-                return '31415';
-            },
-            'generatePreKey': function (keyid) {
-                return Promise.resolve({
-                    'keyId': keyid,
-                    'keyPair': {
-                        'pubKey': 1234,
-                        'privKey': 4321
-                    }
-                });
-            },
-            'generateSignedPreKey': function (identity_keypair, keyid) {
-                return Promise.resolve({
-                    'keyId': keyid,
-                    'keyPair': {
-                        'pubKey': 1234,
-                        'privKey': 4321
-                    }
-                });
-            }
-        }
-    };
-
     describe("The OMEMO module", function() {
 
         it("will add processing hints to sent out encrypted <message> stanzas",
@@ -114,6 +82,31 @@
                 expect(devicelist.devices.at(0).get('id')).toBe('482886413b977930064a5888b92134fe');
 
                 test_utils.openChatBoxFor(_converse, contact_jid);
+                return test_utils.waitUntil(() => {
+                    return _.filter(_converse.connection.IQ_stanzas, function (iq) {
+                        const node = iq.nodeTree.querySelector('publish[xmlns="eu.siacs.conversations.axolotl.devicelist"]');
+                        if (node) { iq_stanza = iq.nodeTree; }
+                        return node;
+                    }).length;
+                });
+            }).then(function () {
+                expect(iq_stanza.outerHTML).toBe(
+                    '<iq from="dummy@localhost" type="set" xmlns="jabber:client" id="'+iq_stanza.getAttribute('id')+'">'+
+                        '<pubsub xmlns="http://jabber.org/protocol/pubsub">'+
+                            '<publish xmlns="eu.siacs.conversations.axolotl.devicelist">'+
+                                '<item>'+
+                                    '<list xmlns="eu.siacs.conversations.axolotl"/>'+
+                                    '<device id="482886413b977930064a5888b92134fe"/>'+
+                                '</item>'+
+                            '</publish>'+
+                    '</pubsub>'+
+                    '</iq>');
+                const stanza = $iq({
+                    'from': _converse.bare_jid,
+                    'id': iq_stanza.getAttribute('id'),
+                    'to': _converse.bare_jid,
+                    'type': 'result'});
+                _converse.connection._dataRecv(test_utils.createRequest(stanza));
                 return test_utils.waitUntil(() => {
                     return _.filter(
                         _converse.connection.IQ_stanzas,

+ 5 - 5
spec/presence.js

@@ -47,7 +47,7 @@
                 "<presence xmlns='jabber:client'>"+
                     "<status>Hello world</status>"+
                     "<priority>0</priority>"+
-                    "<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='1J7kq1MEvnB6ea6vKcgCsSE37gw='/>"+
+                    "<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='3RLZIW6Gu1JDLZXCD6HFV9MiDQ4='/>"+
                 "</presence>"
             );
             _converse.priority = 2;
@@ -57,7 +57,7 @@
                     "<show>away</show>"+
                     "<status>Going jogging</status>"+
                     "<priority>2</priority>"+
-                    "<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='1J7kq1MEvnB6ea6vKcgCsSE37gw='/>"+
+                    "<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='3RLZIW6Gu1JDLZXCD6HFV9MiDQ4='/>"+
                 "</presence>"
             );
 
@@ -68,7 +68,7 @@
                     "<show>dnd</show>"+
                     "<status>Doing taxes</status>"+
                     "<priority>0</priority>"+
-                    "<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='1J7kq1MEvnB6ea6vKcgCsSE37gw='/>"+
+                    "<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='3RLZIW6Gu1JDLZXCD6HFV9MiDQ4='/>"+
                 "</presence>"
             );
         }));
@@ -97,7 +97,7 @@
                     .toBe("<presence xmlns='jabber:client'>"+
                           "<status>My custom status</status>"+
                           "<priority>0</priority>"+
-                          "<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='1J7kq1MEvnB6ea6vKcgCsSE37gw='/>"+
+                          "<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='3RLZIW6Gu1JDLZXCD6HFV9MiDQ4='/>"+
                           "</presence>")
 
                 return test_utils.waitUntil(function () {
@@ -113,7 +113,7 @@
                 modal.el.querySelector('[type="submit"]').click();
                 expect(_converse.connection.send.calls.mostRecent().args[0].toLocaleString())
                     .toBe("<presence xmlns='jabber:client'><show>dnd</show><status>My custom status</status><priority>0</priority>"+
-                          "<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='1J7kq1MEvnB6ea6vKcgCsSE37gw='/>"+
+                          "<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='3RLZIW6Gu1JDLZXCD6HFV9MiDQ4='/>"+
                           "</presence>")
                 done();
             });

+ 37 - 6
src/converse-omemo.js

@@ -188,6 +188,27 @@
                             reject,
                             _converse.IQ_TIMEOUT);
                     });
+                },
+
+                addDeviceToList () {
+                    /* Add this device to our list of devices stored on the
+                     * server.
+                     * https://xmpp.org/extensions/xep-0384.html#usecases-announcing
+                     */
+                    return new Promise((resolve, reject) => {
+                        const stanza = $iq({
+                            'from': _converse.bare_jid,
+                            'type': 'set'
+                        }).c('pubsub', {'xmlns': Strophe.NS.PUBSUB})
+                            .c('publish', {'xmlns': Strophe.NS.OMEMO_DEVICELIST})
+                                .c('item')
+                                    .c('list', {'xmlns': Strophe.NS.OMEMO}).up()
+
+                        this.devices.each((device) => {
+                            stanza.c('device', {'id': device.get('id')}).up();
+                        });
+                        _converse.connection.sendIQ(stanza, resolve, reject, _converse.IQ_TIMEOUT);
+                    }).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
                 }
             });
 
@@ -226,10 +247,7 @@
                 return new Promise((resolve, reject) => _converse.devicelists.fetch({'success': resolve}));
             }
 
-            function updateOwnDeviceList () {
-                /* If our own device is not on the list, add it.
-                 * Also, deduplicate devices if necessary.
-                 */
+            function fetchOwnDevices () {
                 return new Promise((resolve, reject) => {
                     fetchDeviceLists().then(() => {
                         let own_devicelist = _converse.devicelists.get(_converse.bare_jid);
@@ -237,12 +255,23 @@
                             own_devicelist = _converse.devicelists.create({'jid': _converse.bare_jid});
                         }
                         own_devicelist.fetchDevices().then(resolve).catch(reject);
-                        // TODO: if our own device is not onthe list, add it.
-                        // TODO: deduplicate
                     });
                 });
             }
 
+            function updateOwnDeviceList () {
+                /* If our own device is not on the list, add it.
+                 * Also, deduplicate devices if necessary.
+                 */
+                return new Promise((resolve, reject) => {
+                    const devicelist = _converse.devicelists.get(_converse.bare_jid);
+                    if (!devicelist.devices.findWhere({'id': _converse.omemo_store.get('device_id')})) {
+                        return devicelist.addDeviceToList().then(resolve).catch(reject);
+                    }
+                    resolve();
+                });
+            }
+
             function updateDevicesFromStanza (stanza) {
                 // TODO: check whether our own device_id is still on the list,
                 // otherwise we need to update it.
@@ -268,6 +297,7 @@
                 _converse.connection.addHandler((message) => {
                     if (message.querySelector('event[xmlns="'+Strophe.NS.PUBSUB+'#event"]')) {
                         updateDevicesFromStanza(message);
+                        updateOwnDeviceList();
                     }
                 }, null, 'message', 'headline', null, _converse.bare_jid);
             }
@@ -298,6 +328,7 @@
                 );
                 restoreOMEMOSession()
                     .then(() => publishBundle())
+                    .then(() => fetchOwnDevices())
                     .then(() => updateOwnDeviceList())
                     .then(() => _converse.emit('OMEMOInitialized'))
                     .catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));

+ 33 - 1
tests/mock.js

@@ -5,8 +5,40 @@
     var Promise = converse.env.Promise;
     var Strophe = converse.env.Strophe;
     var $iq = converse.env.$iq;
-    var mock = {};
 
+    window.libsignal = {
+        'KeyHelper': {
+            'generateIdentityKeyPair': function () {
+                return Promise.resolve({
+                    'pubKey': 1234,
+                    'privKey': 4321
+                });
+            },
+            'generateRegistrationId': function () {
+                return '31415';
+            },
+            'generatePreKey': function (keyid) {
+                return Promise.resolve({
+                    'keyId': keyid,
+                    'keyPair': {
+                        'pubKey': 1234,
+                        'privKey': 4321
+                    }
+                });
+            },
+            'generateSignedPreKey': function (identity_keypair, keyid) {
+                return Promise.resolve({
+                    'keyId': keyid,
+                    'keyPair': {
+                        'pubKey': 1234,
+                        'privKey': 4321
+                    }
+                });
+            }
+        }
+    };
+
+    var mock = {};
     mock.view_mode = 'overlayed';
 
     // Names from http://www.fakenamegenerator.com/