Commit ddd0ef8e authored by JC Brand's avatar JC Brand

Test that device lists can get updated via PEP

Fix various bugs in the process.

updates #497
parent 41db49ff
...@@ -320,52 +320,54 @@ ...@@ -320,52 +320,54 @@
[{'category': 'pubsub', 'type': 'pep'}], [{'category': 'pubsub', 'type': 'pep'}],
['http://jabber.org/protocol/pubsub#publish-options'] ['http://jabber.org/protocol/pubsub#publish-options']
).then(function () { ).then(function () {
test_utils.waitUntil(function () { return test_utils.waitUntil(() => _converse.bookmarks);
return _converse.bookmarks; }).then(function () {
}, 300).then(function () { // Emit here instead of mocking fetching of bookmarks.
/* The stored data is automatically pushed to all of the user's _converse.emit('bookmarksInitialized');
* connected resources.
*
* Publisher receives event notification
* -------------------------------------
* <message from='juliet@capulet.lit'
* to='juliet@capulet.lit/balcony'
* type='headline'
* id='rnfoo1'>
* <event xmlns='http://jabber.org/protocol/pubsub#event'>
* <items node='storage:bookmarks'>
* <item id='current'>
* <storage xmlns='storage:bookmarks'>
* <conference name='The Play&apos;s the Thing'
* autojoin='true'
* jid='theplay@conference.shakespeare.lit'>
* <nick>JC</nick>
* </conference>
* </storage>
* </item>
* </items>
* </event>
* </message>
*/
var stanza = $msg({
'from': 'dummy@localhost',
'to': 'dummy@localhost/resource',
'type': 'headline',
'id': 'rnfoo1'
}).c('event', {'xmlns': 'http://jabber.org/protocol/pubsub#event'})
.c('items', {'node': 'storage:bookmarks'})
.c('item', {'id': 'current'})
.c('storage', {'xmlns': 'storage:bookmarks'})
.c('conference', {'name': 'The Play&apos;s the Thing',
'autojoin': 'true',
'jid':'theplay@conference.shakespeare.lit'})
.c('nick').t('JC');
_converse.connection._dataRecv(test_utils.createRequest(stanza)); /* The stored data is automatically pushed to all of the user's
expect(_converse.bookmarks.length).toBe(1); * connected resources.
expect(_converse.chatboxviews.get('theplay@conference.shakespeare.lit')).not.toBeUndefined(); *
done(); * Publisher receives event notification
}); * -------------------------------------
* <message from='juliet@capulet.lit'
* to='juliet@capulet.lit/balcony'
* type='headline'
* id='rnfoo1'>
* <event xmlns='http://jabber.org/protocol/pubsub#event'>
* <items node='storage:bookmarks'>
* <item id='current'>
* <storage xmlns='storage:bookmarks'>
* <conference name='The Play&apos;s the Thing'
* autojoin='true'
* jid='theplay@conference.shakespeare.lit'>
* <nick>JC</nick>
* </conference>
* </storage>
* </item>
* </items>
* </event>
* </message>
*/
var stanza = $msg({
'from': 'dummy@localhost',
'to': 'dummy@localhost/resource',
'type': 'headline',
'id': 'rnfoo1'
}).c('event', {'xmlns': 'http://jabber.org/protocol/pubsub#event'})
.c('items', {'node': 'storage:bookmarks'})
.c('item', {'id': 'current'})
.c('storage', {'xmlns': 'storage:bookmarks'})
.c('conference', {'name': 'The Play&apos;s the Thing',
'autojoin': 'true',
'jid':'theplay@conference.shakespeare.lit'})
.c('nick').t('JC');
_converse.connection._dataRecv(test_utils.createRequest(stanza));
return test_utils.waitUntil(() => _converse.bookmarks.length);
}).then(function () {
expect(_converse.bookmarks.length).toBe(1);
expect(_converse.chatboxviews.get('theplay@conference.shakespeare.lit')).not.toBeUndefined();
done();
}); });
})); }));
......
This diff is collapsed.
...@@ -579,8 +579,10 @@ ...@@ -579,8 +579,10 @@
// Add a handler for bookmarks pushed from other connected clients // Add a handler for bookmarks pushed from other connected clients
// (from the same user obviously) // (from the same user obviously)
_converse.connection.addHandler((message) => { _converse.connection.addHandler((message) => {
if (message.querySelector('event[xmlns="'+Strophe.NS.PUBSUB+'#event"]')) { if (sizzle('event[xmlns="'+Strophe.NS.PUBSUB+'#event"] items[node="storage:bookmarks"]', message).length) {
_converse.bookmarks.createBookmarksFromStanza(message); _converse.api.waitUntil('bookmarksInitialized')
.then(() => _converse.bookmarks.createBookmarksFromStanza(message))
.catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
} }
}, null, 'message', 'headline', null, _converse.bare_jid); }, null, 'message', 'headline', null, _converse.bare_jid);
}); });
......
...@@ -519,11 +519,11 @@ ...@@ -519,11 +519,11 @@
'from': _converse.bare_jid, 'from': _converse.bare_jid,
'type': 'set' 'type': 'set'
}).c('pubsub', {'xmlns': Strophe.NS.PUBSUB}) }).c('pubsub', {'xmlns': Strophe.NS.PUBSUB})
.c('publish', {'xmlns': Strophe.NS.OMEMO_DEVICELIST}) .c('publish', {'node': Strophe.NS.OMEMO_DEVICELIST})
.c('item') .c('item')
.c('list', {'xmlns': Strophe.NS.OMEMO}).up() .c('list', {'xmlns': Strophe.NS.OMEMO}).up()
this.devices.each((device) => { _.each(this.devices.where({'active': true}), (device) => {
stanza.c('device', {'id': device.get('id')}).up(); stanza.c('device', {'id': device.get('id')}).up();
}); });
_converse.connection.sendIQ(stanza, resolve, reject, _converse.IQ_TIMEOUT); _converse.connection.sendIQ(stanza, resolve, reject, _converse.IQ_TIMEOUT);
...@@ -584,48 +584,59 @@ ...@@ -584,48 +584,59 @@
/* If our own device is not on the list, add it. /* If our own device is not on the list, add it.
* Also, deduplicate devices if necessary. * Also, deduplicate devices if necessary.
*/ */
return new Promise((resolve, reject) => { const devicelist = _converse.devicelists.get(_converse.bare_jid),
restoreOMEMOSession().then(() => { device_id = _converse.omemo_store.get('device_id'),
const devicelist = _converse.devicelists.get(_converse.bare_jid); own_device = devicelist.devices.findWhere({'id': device_id});
const device_id = _converse.omemo_store.get('device_id');
if (!devicelist.devices.findWhere({'id': device_id})) { if (!own_device) {
return devicelist.addDeviceToList(device_id).then(resolve).catch(reject); return devicelist.addDeviceToList(device_id);
} } else if (!own_device.get('active')) {
resolve(); own_device.set('active', true, {'silent': true});
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR)); return devicelist.addDeviceToList(device_id);
}); } else {
return Promise.resolve();
}
} }
function updateBundleFromStanza (stanza) { function updateBundleFromStanza (stanza) {
const items_el = sizzle(`items[node="${Strophe.NS.OMEMO_BUNDLES}"]`, stanza), const items_el = sizzle(`items[node="${Strophe.NS.OMEMO_BUNDLES}"]`, stanza).pop();
device_id = items_el.getAttribute('node').split(':')[1], if (!items_el) {
return;
}
const device_id = items_el.getAttribute('node').split(':')[1],
from = stanza.getAttribute('from'), from = stanza.getAttribute('from'),
bundle_el = sizzle(`item list[xmlns="${Strophe.NS.OMEMO}"] bundle`, items_el).pop(), bundle_el = sizzle(`item list[xmlns="${Strophe.NS.OMEMO}"] bundle`, items_el).pop(),
bundle = parseBundle(bundle_el); device = _converse.devicelists.get(from).devices.get(device_id);
device.save({'bundle': parseBundle(bundle_el)});
const device = _converse.devicelists.get(from).devices.get(device_id);
device.save({'bundle': bundle});
} }
function updateDevicesFromStanza (stanza) { function updateDevicesFromStanza (stanza) {
// TODO: check whether our own device_id is still on the list, const items_el = sizzle(`items[node="${Strophe.NS.OMEMO_DEVICELIST}"]`, stanza).pop();
// otherwise we need to update it. if (!items_el) {
return;
}
const device_ids = _.map( const device_ids = _.map(
sizzle(`items[node="${Strophe.NS.OMEMO_DEVICELIST}"] item list[xmlns="${Strophe.NS.OMEMO}"] device`, stanza), sizzle(`item list[xmlns="${Strophe.NS.OMEMO}"] device`, items_el),
(device) => device.getAttribute('id')); (device) => device.getAttribute('id')
);
const removed_ids = _.difference(_converse.devices.pluck('id'), device_ids); const jid = stanza.getAttribute('from'),
_.forEach(removed_ids, (removed_id) => _converse.devices.get(removed_id).set('active', false)); devicelist = _converse.devicelists.get(jid) || _converse.devicelists.create({'jid': jid}),
devices = devicelist.devices,
removed_ids = _.difference(devices.pluck('id'), device_ids);
_.forEach(removed_ids, (removed_id) => devices.get(removed_id).set('active', false));
_.forEach(device_ids, (device_id) => { _.forEach(device_ids, (device_id) => {
const dev = _converse.devices.get(device_id); const dev = devices.get(device_id);
if (dev) { if (dev) {
dev.save({'active': true}); dev.save({'active': true});
} else { } else {
_converse.devices.create({'id': device_id}) devices.create({'id': device_id})
} }
}); });
// Make sure our own device is on the list (i.e. if it was
// removed, add it again.
updateOwnDeviceList();
} }
function registerPEPPushHandler () { function registerPEPPushHandler () {
...@@ -634,9 +645,9 @@ ...@@ -634,9 +645,9 @@
if (message.querySelector('event[xmlns="'+Strophe.NS.PUBSUB+'#event"]')) { if (message.querySelector('event[xmlns="'+Strophe.NS.PUBSUB+'#event"]')) {
updateDevicesFromStanza(message); updateDevicesFromStanza(message);
updateBundleFromStanza(message); updateBundleFromStanza(message);
updateOwnDeviceList();
} }
}, null, 'message', 'headline', null, _converse.bare_jid); return true;
}, null, 'message', 'headline');
} }
function restoreOMEMOSession () { function restoreOMEMOSession () {
...@@ -655,6 +666,7 @@ ...@@ -655,6 +666,7 @@
b64_sha1(`converse.devicelists-${_converse.bare_jid}`) b64_sha1(`converse.devicelists-${_converse.bare_jid}`)
); );
fetchOwnDevices() fetchOwnDevices()
.then(() => restoreOMEMOSession())
.then(() => updateOwnDeviceList()) .then(() => updateOwnDeviceList())
.then(() => publishBundle()) .then(() => publishBundle())
.then(() => _converse.emit('OMEMOInitialized')) .then(() => _converse.emit('OMEMOInitialized'))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment