Updated so that own device is properly created and published
Based on live testing. Updated tests accordingly.
This commit is contained in:
parent
a422f07866
commit
fa0e7aeff5
246
dist/converse.js
vendored
246
dist/converse.js
vendored
@ -63067,9 +63067,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
* that contains the message stanza, if it was
|
* that contains the message stanza, if it was
|
||||||
* contained, otherwise it's the message stanza itself.
|
* contained, otherwise it's the message stanza itself.
|
||||||
*/
|
*/
|
||||||
const _converse = this.__super__._converse,
|
const archive = sizzle(`result[xmlns="${Strophe.NS.MAM}"]`, original_stanza).pop(),
|
||||||
__ = _converse.__,
|
|
||||||
archive = sizzle(`result[xmlns="${Strophe.NS.MAM}"]`, original_stanza).pop(),
|
|
||||||
spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, original_stanza).pop(),
|
spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, original_stanza).pop(),
|
||||||
delay = sizzle(`delay[xmlns="${Strophe.NS.DELAY}"]`, original_stanza).pop(),
|
delay = sizzle(`delay[xmlns="${Strophe.NS.DELAY}"]`, original_stanza).pop(),
|
||||||
chat_state = stanza.getElementsByTagName(_converse.COMPOSING).length && _converse.COMPOSING || stanza.getElementsByTagName(_converse.PAUSED).length && _converse.PAUSED || stanza.getElementsByTagName(_converse.INACTIVE).length && _converse.INACTIVE || stanza.getElementsByTagName(_converse.ACTIVE).length && _converse.ACTIVE || stanza.getElementsByTagName(_converse.GONE).length && _converse.GONE;
|
chat_state = stanza.getElementsByTagName(_converse.COMPOSING).length && _converse.COMPOSING || stanza.getElementsByTagName(_converse.PAUSED).length && _converse.PAUSED || stanza.getElementsByTagName(_converse.INACTIVE).length && _converse.INACTIVE || stanza.getElementsByTagName(_converse.ACTIVE).length && _converse.ACTIVE || stanza.getElementsByTagName(_converse.GONE).length && _converse.GONE;
|
||||||
@ -63775,10 +63773,12 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
emojione.ascii = true;
|
emojione.ascii = true;
|
||||||
|
|
||||||
function onWindowStateChanged(data) {
|
function onWindowStateChanged(data) {
|
||||||
_converse.chatboxviews.each(function (chatboxview) {
|
if (_converse.chatboxviews) {
|
||||||
|
_converse.chatboxviews.each(chatboxview => {
|
||||||
chatboxview.onWindowStateChanged(data.state);
|
chatboxview.onWindowStateChanged(data.state);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_converse.api.listen.on('windowStateChanged', onWindowStateChanged);
|
_converse.api.listen.on('windowStateChanged', onWindowStateChanged);
|
||||||
|
|
||||||
@ -66011,11 +66011,11 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
|
|
||||||
_converse.connection.reset();
|
_converse.connection.reset();
|
||||||
|
|
||||||
_converse.off();
|
|
||||||
|
|
||||||
_converse.stopListening();
|
_converse.stopListening();
|
||||||
|
|
||||||
_converse.tearDown();
|
_converse.tearDown();
|
||||||
|
|
||||||
|
_converse.off();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('onpagehide' in window) {
|
if ('onpagehide' in window) {
|
||||||
@ -69986,6 +69986,10 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
});
|
});
|
||||||
|
|
||||||
_converse.api.listen.on('afterTearDown', () => {
|
_converse.api.listen.on('afterTearDown', () => {
|
||||||
|
if (!_converse.chatboxviews) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const container = _converse.chatboxviews.el.querySelector("#converse-modals");
|
const container = _converse.chatboxviews.el.querySelector("#converse-modals");
|
||||||
|
|
||||||
if (container) {
|
if (container) {
|
||||||
@ -74075,6 +74079,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
this.devicelist = _converse.devicelists.get(_converse.bare_jid);
|
this.devicelist = _converse.devicelists.get(_converse.bare_jid);
|
||||||
this.devicelist.devices.on('change:bundle', this.debouncedRender, this);
|
this.devicelist.devices.on('change:bundle', this.debouncedRender, this);
|
||||||
this.devicelist.devices.on('reset', this.debouncedRender, this);
|
this.devicelist.devices.on('reset', this.debouncedRender, this);
|
||||||
|
this.devicelist.devices.on('remove', this.debouncedRender, this);
|
||||||
return this.__super__.initialize.apply(this, arguments);
|
return this.__super__.initialize.apply(this, arguments);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -74131,6 +74136,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
});
|
});
|
||||||
this.devicelist.devices.on('change:bundle', this.render, this);
|
this.devicelist.devices.on('change:bundle', this.render, this);
|
||||||
this.devicelist.devices.on('change:trusted', this.render, this);
|
this.devicelist.devices.on('change:trusted', this.render, this);
|
||||||
|
this.devicelist.devices.on('remove', this.render, this);
|
||||||
|
this.devicelist.devices.on('reset', this.render, this);
|
||||||
return this.__super__.initialize.apply(this, arguments);
|
return this.__super__.initialize.apply(this, arguments);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -74162,9 +74169,11 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
address = new libsignal.SignalProtocolAddress(device.get('jid'), device.get('id')),
|
address = new libsignal.SignalProtocolAddress(device.get('jid'), device.get('id')),
|
||||||
sessionBuilder = new libsignal.SessionBuilder(_converse.omemo_store, address),
|
sessionBuilder = new libsignal.SessionBuilder(_converse.omemo_store, address),
|
||||||
prekey = device.getRandomPreKey();
|
prekey = device.getRandomPreKey();
|
||||||
|
|
||||||
|
try {
|
||||||
return sessionBuilder.processPreKey({
|
return sessionBuilder.processPreKey({
|
||||||
'registrationId': _converse.omemo_store.get('registration_id'),
|
'registrationId': parseInt(_converse.omemo_store.get('device_id'), 10),
|
||||||
'identityKey': _converse.omemo_store.get('identity_keypair'),
|
'identityKey': _converse.omemo_store.get('identity_key'),
|
||||||
'signedPreKey': {
|
'signedPreKey': {
|
||||||
'keyId': bundle.signed_prekey.id,
|
'keyId': bundle.signed_prekey.id,
|
||||||
// <Number>
|
// <Number>
|
||||||
@ -74177,6 +74186,13 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
'publicKey': u.base64ToArrayBuffer(prekey.key)
|
'publicKey': u.base64ToArrayBuffer(prekey.key)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} catch (e) {
|
||||||
|
_converse.log(`Error: could not build session for device ${device.get('id')}`, Strophe.LogLevel.ERROR);
|
||||||
|
|
||||||
|
_converse.log(e.message, Strophe.LogLevel.ERROR);
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getKeyAndTag(string) {
|
getKeyAndTag(string) {
|
||||||
@ -74447,21 +74463,14 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
_converse.NUM_PREKEYS = 100; // Set here so that tests can override
|
_converse.NUM_PREKEYS = 100; // Set here so that tests can override
|
||||||
|
|
||||||
function generateFingerprint(device) {
|
function generateFingerprint(device) {
|
||||||
return new Promise((resolve, reject) => {
|
let bundle;
|
||||||
device.getBundle().then(bundle => {
|
return device.getBundle().then(b => {
|
||||||
if (_.isNil(bundle)) {
|
bundle = b;
|
||||||
resolve();
|
return crypto.subtle.digest('SHA-1', u.base64ToArrayBuffer(bundle['identity_key']));
|
||||||
} // TODO: only generate fingerprints when necessary
|
}).then(fp => {
|
||||||
|
|
||||||
|
|
||||||
crypto.subtle.digest('SHA-1', u.base64ToArrayBuffer(bundle['identity_key'])).then(fp => {
|
|
||||||
bundle['fingerprint'] = u.arrayBufferToHex(fp);
|
bundle['fingerprint'] = u.arrayBufferToHex(fp);
|
||||||
device.save('bundle', bundle);
|
device.save('bundle', bundle);
|
||||||
device.trigger('change:bundle'); // Doesn't get triggered automatically due to pass-by-reference
|
device.trigger('change:bundle'); // Doesn't get triggered automatically due to pass-by-reference
|
||||||
|
|
||||||
resolve();
|
|
||||||
}).catch(reject);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74470,19 +74479,13 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
};
|
};
|
||||||
|
|
||||||
_converse.getDevicesForContact = function (jid) {
|
_converse.getDevicesForContact = function (jid) {
|
||||||
return new Promise((resolve, reject) => {
|
let devicelist;
|
||||||
_converse.api.waitUntil('OMEMOInitialized').then(() => {
|
return _converse.api.waitUntil('OMEMOInitialized').then(() => {
|
||||||
let devicelist = _converse.devicelists.get(jid);
|
devicelist = _converse.devicelists.get(jid) || _converse.devicelists.create({
|
||||||
|
|
||||||
if (_.isNil(devicelist)) {
|
|
||||||
devicelist = _converse.devicelists.create({
|
|
||||||
'jid': jid
|
'jid': jid
|
||||||
});
|
});
|
||||||
}
|
return devicelist.fetchDevices();
|
||||||
|
}).then(() => devicelist.devices);
|
||||||
devicelist.fetchDevices().then(() => resolve(devicelist.devices));
|
|
||||||
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_converse.contactHasOMEMOSupport = function (jid) {
|
_converse.contactHasOMEMOSupport = function (jid) {
|
||||||
@ -74508,35 +74511,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return device_id;
|
return device_id.toString();
|
||||||
}
|
|
||||||
|
|
||||||
function generateBundle() {
|
|
||||||
/* The first thing that needs to happen if a client wants to
|
|
||||||
* start using OMEMO is they need to generate an IdentityKey
|
|
||||||
* and a Device ID. The IdentityKey is a Curve25519 [6]
|
|
||||||
* public/private Key pair. The Device ID is a randomly
|
|
||||||
* generated integer between 1 and 2^31 - 1.
|
|
||||||
*/
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
libsignal.KeyHelper.generateIdentityKeyPair().then(identity_keypair => {
|
|
||||||
const data = {
|
|
||||||
'device_id': generateDeviceID(),
|
|
||||||
'identity_keypair': identity_keypair,
|
|
||||||
'prekeys': {}
|
|
||||||
};
|
|
||||||
libsignal.KeyHelper.generateSignedPreKey(identity_keypair, 0).then(signed_prekey => {
|
|
||||||
data['signed_prekey'] = signed_prekey;
|
|
||||||
|
|
||||||
const key_promises = _.map(_.range(0, _converse.NUM_PREKEYS), id => libsignal.KeyHelper.generatePreKey(id));
|
|
||||||
|
|
||||||
Promise.all(key_promises).then(keys => {
|
|
||||||
data['prekeys'] = keys;
|
|
||||||
resolve(data);
|
|
||||||
});
|
|
||||||
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
|
||||||
});
|
|
||||||
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_converse.OMEMOStore = Backbone.Model.extend({
|
_converse.OMEMOStore = Backbone.Model.extend({
|
||||||
@ -74666,11 +74641,39 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
|
|
||||||
createNewDeviceBundle() {
|
generateBundle() {
|
||||||
return generateBundle().then(data => {
|
/* The first thing that needs to happen if a client wants to
|
||||||
// TODO: should storeSession be used here?
|
* start using OMEMO is they need to generate an IdentityKey
|
||||||
_converse.omemo_store.save(data);
|
* and a Device ID. The IdentityKey is a Curve25519 [6]
|
||||||
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
* public/private Key pair. The Device ID is a randomly
|
||||||
|
* generated integer between 1 and 2^31 - 1.
|
||||||
|
*/
|
||||||
|
const data = {
|
||||||
|
'device_id': generateDeviceID()
|
||||||
|
};
|
||||||
|
return libsignal.KeyHelper.generateIdentityKeyPair().then(identity_keypair => {
|
||||||
|
data['identity_keypair'] = identity_keypair;
|
||||||
|
data['identity_key'] = identity_keypair.pubKey;
|
||||||
|
return libsignal.KeyHelper.generateSignedPreKey(identity_keypair, 1);
|
||||||
|
}).then(signed_prekey => {
|
||||||
|
_converse.omemo_store.storeSignedPreKey(signed_prekey.keyId, signed_prekey.keyPair);
|
||||||
|
|
||||||
|
data['signed_prekey'] = signed_prekey;
|
||||||
|
return Promise.all(_.map(_.range(0, _converse.NUM_PREKEYS), id => libsignal.KeyHelper.generatePreKey(id)));
|
||||||
|
}).then(keys => {
|
||||||
|
_.forEach(keys, k => _converse.omemo_store.storePreKey(k.keyId, k.keyPair));
|
||||||
|
|
||||||
|
data['prekeys'] = keys;
|
||||||
|
this.save(data); // Save the bundle to the device
|
||||||
|
|
||||||
|
const devicelist = _converse.devicelists.get(_converse.bare_jid),
|
||||||
|
device = devicelist.devices.create({
|
||||||
|
'id': data.device_id,
|
||||||
|
'jid': _converse.bare_jid
|
||||||
|
});
|
||||||
|
|
||||||
|
device.save('bundle', data);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchSession() {
|
fetchSession() {
|
||||||
@ -74679,13 +74682,13 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
this.fetch({
|
this.fetch({
|
||||||
'success': () => {
|
'success': () => {
|
||||||
if (!_converse.omemo_store.get('device_id')) {
|
if (!_converse.omemo_store.get('device_id')) {
|
||||||
this.createNewDeviceBundle().then(resolve).catch(resolve);
|
this.generateBundle().then(resolve).catch(resolve);
|
||||||
} else {
|
} else {
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'error': () => {
|
'error': () => {
|
||||||
this.createNewDeviceBundle().then(resolve).catch(resolve);
|
this.generateBundle().then(resolve).catch(resolve);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -74760,13 +74763,13 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
this.devices.fetch({
|
this.devices.fetch({
|
||||||
'success': collection => {
|
'success': collection => {
|
||||||
if (collection.length === 0) {
|
if (collection.length === 0) {
|
||||||
this.fetchDevicesFromServer().then(resolve).catch(reject);
|
this.fetchDevicesFromServer().then(ids => this.publishCurrentDevice(ids)).then(resolve).catch(resolve);
|
||||||
} else {
|
} else {
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'error': () => {
|
'error': () => {
|
||||||
this.fetchDevicesFromServer().then(resolve).catch(reject);
|
this.fetchDevicesFromServer().then(ids => this.publishCurrentDevice(ids)).then(resolve).catch(resolve);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -74775,8 +74778,33 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
return this._devices_promise;
|
return this._devices_promise;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
publishCurrentDevice(device_ids) {
|
||||||
|
if (this.get('jid') !== _converse.bare_jid) {
|
||||||
|
// We only publish for ourselves.
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
return restoreOMEMOSession().then(() => {
|
||||||
|
const device_id = _converse.omemo_store.get('device_id');
|
||||||
|
|
||||||
|
if (!_.includes(device_ids, device_id)) {
|
||||||
|
return this.publishDevices();
|
||||||
|
} else {
|
||||||
|
const own_device = this.devices.findWhere({
|
||||||
|
'id': device_id
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!own_device.get('active')) {
|
||||||
|
own_device.set('active', true, {
|
||||||
|
'silent': true
|
||||||
|
});
|
||||||
|
return this.publishDevices();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
fetchDevicesFromServer() {
|
fetchDevicesFromServer() {
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const stanza = $iq({
|
const stanza = $iq({
|
||||||
'type': 'get',
|
'type': 'get',
|
||||||
'from': _converse.bare_jid,
|
'from': _converse.bare_jid,
|
||||||
@ -74786,15 +74814,15 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
}).c('items', {
|
}).c('items', {
|
||||||
'node': Strophe.NS.OMEMO_DEVICELIST
|
'node': Strophe.NS.OMEMO_DEVICELIST
|
||||||
});
|
});
|
||||||
|
return _converse.api.sendIQ(stanza).then(iq => {
|
||||||
|
const device_ids = _.map(sizzle(`list[xmlns="${Strophe.NS.OMEMO}"] device`, iq), dev => dev.getAttribute('id'));
|
||||||
|
|
||||||
_converse.connection.sendIQ(stanza, iq => {
|
_.forEach(device_ids, id => this.devices.create({
|
||||||
_.forEach(sizzle(`list[xmlns="${Strophe.NS.OMEMO}"] device`, iq), dev => this.devices.create({
|
'id': id,
|
||||||
'id': dev.getAttribute('id'),
|
|
||||||
'jid': this.get('jid')
|
'jid': this.get('jid')
|
||||||
}));
|
}));
|
||||||
|
|
||||||
resolve();
|
return device_ids;
|
||||||
}, reject, _converse.IQ_TIMEOUT);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -74821,22 +74849,6 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
return _converse.api.sendIQ(stanza);
|
return _converse.api.sendIQ(stanza);
|
||||||
},
|
},
|
||||||
|
|
||||||
addOwnDevice(device_id) {
|
|
||||||
/* Add this device to our list of devices stored on the
|
|
||||||
* server.
|
|
||||||
* https://xmpp.org/extensions/xep-0384.html#usecases-announcing
|
|
||||||
*/
|
|
||||||
if (this.get('jid') !== _converse.bare_jid) {
|
|
||||||
throw new Error("Cannot add device to someone else's device list");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.devices.create({
|
|
||||||
'id': device_id.toString(),
|
|
||||||
'jid': this.get('jid')
|
|
||||||
});
|
|
||||||
return this.publishDevices();
|
|
||||||
},
|
|
||||||
|
|
||||||
removeOwnDevices(device_ids) {
|
removeOwnDevices(device_ids) {
|
||||||
if (this.get('jid') !== _converse.bare_jid) {
|
if (this.get('jid') !== _converse.bare_jid) {
|
||||||
throw new Error("Cannot remove devices from someone else's device list");
|
throw new Error("Cannot remove devices from someone else's device list");
|
||||||
@ -74854,7 +74866,6 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
publishBundle() {
|
publishBundle() {
|
||||||
const store = _converse.omemo_store,
|
const store = _converse.omemo_store,
|
||||||
signed_prekey = store.get('signed_prekey');
|
signed_prekey = store.get('signed_prekey');
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const stanza = $iq({
|
const stanza = $iq({
|
||||||
'from': _converse.bare_jid,
|
'from': _converse.bare_jid,
|
||||||
'type': 'set'
|
'type': 'set'
|
||||||
@ -74874,8 +74885,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
}).t(u.arrayBufferToBase64(prekey.keyPair.pubKey)).up();
|
}).t(u.arrayBufferToBase64(prekey.keyPair.pubKey)).up();
|
||||||
});
|
});
|
||||||
|
|
||||||
_converse.connection.sendIQ(stanza, resolve, reject, _converse.IQ_TIMEOUT);
|
return _converse.api.sendIQ(stanza);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -74901,28 +74911,6 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateOwnDeviceList() {
|
|
||||||
/* If our own device is not on the list, add it.
|
|
||||||
* Also, deduplicate devices if necessary.
|
|
||||||
*/
|
|
||||||
const devicelist = _converse.devicelists.get(_converse.bare_jid),
|
|
||||||
device_id = _converse.omemo_store.get('device_id').toString(),
|
|
||||||
own_device = devicelist.devices.findWhere({
|
|
||||||
'id': device_id
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!own_device) {
|
|
||||||
return devicelist.addOwnDevice(device_id);
|
|
||||||
} else if (!own_device.get('active')) {
|
|
||||||
own_device.set('active', true, {
|
|
||||||
'silent': true
|
|
||||||
});
|
|
||||||
return devicelist.addOwnDevice(device_id);
|
|
||||||
} else {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateBundleFromStanza(stanza) {
|
function updateBundleFromStanza(stanza) {
|
||||||
const items_el = sizzle(`items`, stanza).pop();
|
const items_el = sizzle(`items`, stanza).pop();
|
||||||
|
|
||||||
@ -74977,20 +74965,26 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
'jid': jid
|
'jid': jid
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}); // Make sure our own device is on the list (i.e. if it was
|
});
|
||||||
|
|
||||||
|
if (Strophe.getBareJidFromJid(jid) === _converse.bare_jid) {
|
||||||
|
// Make sure our own device is on the list (i.e. if it was
|
||||||
// removed, add it again.
|
// removed, add it again.
|
||||||
|
_converse.devicelists.get(_converse.bare_jid).publishCurrentDevice(device_ids);
|
||||||
|
}
|
||||||
updateOwnDeviceList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerPEPPushHandler() {
|
function registerPEPPushHandler() {
|
||||||
// Add a handler for devices pushed from other connected clients
|
// Add a handler for devices pushed from other connected clients
|
||||||
_converse.connection.addHandler(message => {
|
_converse.connection.addHandler(message => {
|
||||||
if (message.querySelector('event[xmlns="' + Strophe.NS.PUBSUB + '#event"]')) {
|
try {
|
||||||
|
if (sizzle(`event[xmlns="${Strophe.NS.PUBSUB}#event"]`, message).length) {
|
||||||
updateDevicesFromStanza(message);
|
updateDevicesFromStanza(message);
|
||||||
updateBundleFromStanza(message);
|
updateBundleFromStanza(message);
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
_converse.log(e.message, Strophe.LogLevel.ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}, null, 'message', 'headline');
|
}, null, 'message', 'headline');
|
||||||
@ -75012,10 +75006,14 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
const id = `converse.devicelists-${_converse.bare_jid}`;
|
const id = `converse.devicelists-${_converse.bare_jid}`;
|
||||||
_converse.devicelists.id = id;
|
_converse.devicelists.id = id;
|
||||||
_converse.devicelists.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
|
_converse.devicelists.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
|
||||||
fetchOwnDevices().then(() => restoreOMEMOSession()).then(() => updateOwnDeviceList()).then(() => _converse.omemo.publishBundle()).then(() => _converse.emit('OMEMOInitialized')).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
fetchOwnDevices().then(() => restoreOMEMOSession()).then(() => _converse.omemo.publishBundle()).then(() => _converse.emit('OMEMOInitialized')).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
_converse.api.listen.on('afterTearDown', () => _converse.devicelists.reset());
|
_converse.api.listen.on('afterTearDown', () => {
|
||||||
|
_converse.devicelists.reset();
|
||||||
|
|
||||||
|
delete _converse.omemo_store;
|
||||||
|
});
|
||||||
|
|
||||||
_converse.api.listen.on('connected', registerPEPPushHandler);
|
_converse.api.listen.on('connected', registerPEPPushHandler);
|
||||||
|
|
||||||
@ -75023,7 +75021,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||||||
|
|
||||||
_converse.api.listen.on('statusInitialized', initOMEMO);
|
_converse.api.listen.on('statusInitialized', initOMEMO);
|
||||||
|
|
||||||
_converse.api.listen.on('addClientFeatures', () => _converse.api.disco.own.features.add(Strophe.NS.OMEMO_DEVICELIST + "notify"));
|
_converse.api.listen.on('addClientFeatures', () => _converse.api.disco.own.features.add(`${Strophe.NS.OMEMO_DEVICELIST}+notify`));
|
||||||
|
|
||||||
_converse.api.listen.on('userDetailsModalInitialized', contact => {
|
_converse.api.listen.on('userDetailsModalInitialized', contact => {
|
||||||
const jid = contact.get('jid');
|
const jid = contact.get('jid');
|
||||||
|
@ -621,10 +621,10 @@
|
|||||||
expect(view.model.get('chat_state')).toBe('inactive');
|
expect(view.model.get('chat_state')).toBe('inactive');
|
||||||
spyOn(_converse.connection, 'send');
|
spyOn(_converse.connection, 'send');
|
||||||
view.model.maximize();
|
view.model.maximize();
|
||||||
return test_utils.waitUntil(() => view.model.get('chat_state') === 'active', 700);
|
return test_utils.waitUntil(() => view.model.get('chat_state') === 'active', 1000);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
expect(_converse.connection.send).toHaveBeenCalled();
|
expect(_converse.connection.send).toHaveBeenCalled();
|
||||||
var calls = _.filter(_converse.connection.send.calls.all(), function (call) {
|
const calls = _.filter(_converse.connection.send.calls.all(), function (call) {
|
||||||
return call.args[0] instanceof Strophe.Builder;
|
return call.args[0] instanceof Strophe.Builder;
|
||||||
});
|
});
|
||||||
expect(calls.length).toBe(1);
|
expect(calls.length).toBe(1);
|
||||||
@ -635,7 +635,7 @@
|
|||||||
expect($stanza.children().get(1).tagName).toBe('no-store');
|
expect($stanza.children().get(1).tagName).toBe('no-store');
|
||||||
expect($stanza.children().get(2).tagName).toBe('no-permanent-store');
|
expect($stanza.children().get(2).tagName).toBe('no-permanent-store');
|
||||||
done();
|
done();
|
||||||
});
|
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
182
spec/omemo.js
182
spec/omemo.js
@ -65,10 +65,41 @@
|
|||||||
.c('device', {'id': '482886413b977930064a5888b92134fe'});
|
.c('device', {'id': '482886413b977930064a5888b92134fe'});
|
||||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
|
||||||
_converse.emit('OMEMOInitialized');
|
// Check that own device was published
|
||||||
// Check that device list for contact is fetched when chat is opened.
|
return test_utils.waitUntil(() => {
|
||||||
return test_utils.openChatBoxFor(_converse, contact_jid);
|
return _.filter(
|
||||||
|
_converse.connection.IQ_stanzas,
|
||||||
|
(iq) => {
|
||||||
|
const node = iq.nodeTree.querySelector('iq[from="'+_converse.bare_jid+'"] publish[node="eu.siacs.conversations.axolotl.devicelist"]');
|
||||||
|
if (node) { iq_stanza = iq.nodeTree;}
|
||||||
|
return node;
|
||||||
|
}).length;
|
||||||
|
});
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
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, function (iq) {
|
||||||
|
const node = iq.nodeTree.querySelector('publish[node="eu.siacs.conversations.axolotl.bundles:123456789"]');
|
||||||
|
if (node) { iq_stanza = iq.nodeTree; }
|
||||||
|
return node;
|
||||||
|
}).length;
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
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 _converse.api.waitUntil('OMEMOInitialized');
|
||||||
|
}).then(() => test_utils.openChatBoxFor(_converse, contact_jid))
|
||||||
|
.then(() => {
|
||||||
return test_utils.waitUntil(() => {
|
return test_utils.waitUntil(() => {
|
||||||
return _.filter(
|
return _.filter(
|
||||||
_converse.connection.IQ_stanzas,
|
_converse.connection.IQ_stanzas,
|
||||||
@ -90,7 +121,8 @@
|
|||||||
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
||||||
.c('device', {'id': '555'});
|
.c('device', {'id': '555'});
|
||||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
return test_utils.waitUntil(() => _converse.omemo_store);
|
||||||
|
}).then(() => {
|
||||||
const devicelist = _converse.devicelists.get({'jid': contact_jid});
|
const devicelist = _converse.devicelists.get({'jid': contact_jid});
|
||||||
expect(devicelist.devices.length).toBe(1);
|
expect(devicelist.devices.length).toBe(1);
|
||||||
|
|
||||||
@ -233,7 +265,8 @@
|
|||||||
test_utils.createContacts(_converse, 'current', 1);
|
test_utils.createContacts(_converse, 'current', 1);
|
||||||
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
|
|
||||||
test_utils.waitUntil(function () {
|
// Wait until own devices are fetched
|
||||||
|
test_utils.waitUntil(() => {
|
||||||
return _.filter(
|
return _.filter(
|
||||||
_converse.connection.IQ_stanzas,
|
_converse.connection.IQ_stanzas,
|
||||||
(iq) => {
|
(iq) => {
|
||||||
@ -241,7 +274,7 @@
|
|||||||
if (node) { iq_stanza = iq.nodeTree;}
|
if (node) { iq_stanza = iq.nodeTree;}
|
||||||
return node;
|
return node;
|
||||||
}).length;
|
}).length;
|
||||||
}).then(function () {
|
}).then(() => {
|
||||||
expect(iq_stanza.outerHTML).toBe(
|
expect(iq_stanza.outerHTML).toBe(
|
||||||
'<iq type="get" from="dummy@localhost" to="dummy@localhost" xmlns="jabber:client" id="'+iq_stanza.getAttribute("id")+'">'+
|
'<iq type="get" from="dummy@localhost" to="dummy@localhost" xmlns="jabber:client" id="'+iq_stanza.getAttribute("id")+'">'+
|
||||||
'<pubsub xmlns="http://jabber.org/protocol/pubsub">'+
|
'<pubsub xmlns="http://jabber.org/protocol/pubsub">'+
|
||||||
@ -259,16 +292,48 @@
|
|||||||
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
||||||
.c('device', {'id': '555'});
|
.c('device', {'id': '555'});
|
||||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
return test_utils.waitUntil(() => _converse.omemo_store);
|
||||||
|
}).then(() => {
|
||||||
expect(_converse.devicelists.length).toBe(1);
|
expect(_converse.devicelists.length).toBe(1);
|
||||||
const devicelist = _converse.devicelists.get(_converse.bare_jid);
|
const devicelist = _converse.devicelists.get(_converse.bare_jid);
|
||||||
expect(devicelist.devices.length).toBe(1);
|
expect(devicelist.devices.length).toBe(2);
|
||||||
expect(devicelist.devices.at(0).get('id')).toBe('555');
|
expect(devicelist.devices.at(0).get('id')).toBe('555');
|
||||||
return test_utils.waitUntil(() => _converse.devicelists);
|
expect(devicelist.devices.at(1).get('id')).toBe('123456789');
|
||||||
}).then(function () {
|
|
||||||
// We simply emit, to avoid doing all the setup work
|
|
||||||
_converse.emit('OMEMOInitialized');
|
|
||||||
|
|
||||||
|
// Check that own device was published
|
||||||
|
return test_utils.waitUntil(() => {
|
||||||
|
return _.filter(
|
||||||
|
_converse.connection.IQ_stanzas,
|
||||||
|
(iq) => {
|
||||||
|
const node = iq.nodeTree.querySelector('iq[from="'+_converse.bare_jid+'"] publish[node="eu.siacs.conversations.axolotl.devicelist"]');
|
||||||
|
if (node) { iq_stanza = iq.nodeTree;}
|
||||||
|
return node;
|
||||||
|
}).length;
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
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, function (iq) {
|
||||||
|
const node = iq.nodeTree.querySelector('publish[node="eu.siacs.conversations.axolotl.bundles:123456789"]');
|
||||||
|
if (node) { iq_stanza = iq.nodeTree; }
|
||||||
|
return node;
|
||||||
|
}).length;
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
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 _converse.api.waitUntil('OMEMOInitialized');
|
||||||
|
}).then(() => {
|
||||||
let stanza = $msg({
|
let stanza = $msg({
|
||||||
'from': contact_jid,
|
'from': contact_jid,
|
||||||
'to': _converse.bare_jid,
|
'to': _converse.bare_jid,
|
||||||
@ -319,6 +384,7 @@
|
|||||||
.c('items', {'node': 'eu.siacs.conversations.axolotl.devicelist'})
|
.c('items', {'node': 'eu.siacs.conversations.axolotl.devicelist'})
|
||||||
.c('item')
|
.c('item')
|
||||||
.c('list', {'xmlns': 'eu.siacs.conversations.axolotl'})
|
.c('list', {'xmlns': 'eu.siacs.conversations.axolotl'})
|
||||||
|
.c('device', {'id': '123456789'})
|
||||||
.c('device', {'id': '555'})
|
.c('device', {'id': '555'})
|
||||||
.c('device', {'id': '777'})
|
.c('device', {'id': '777'})
|
||||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
@ -346,7 +412,8 @@
|
|||||||
.c('device', {'id': '444'})
|
.c('device', {'id': '444'})
|
||||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
|
||||||
return test_utils.waitUntil(function () {
|
// Check that own device was published
|
||||||
|
return test_utils.waitUntil(() => {
|
||||||
return _.filter(
|
return _.filter(
|
||||||
_converse.connection.IQ_stanzas,
|
_converse.connection.IQ_stanzas,
|
||||||
(iq) => {
|
(iq) => {
|
||||||
@ -355,7 +422,7 @@
|
|||||||
return node;
|
return node;
|
||||||
}).length;
|
}).length;
|
||||||
});
|
});
|
||||||
}).then(function () {
|
}).then(() => {
|
||||||
// Check that our own device is added again, but that removed
|
// Check that our own device is added again, but that removed
|
||||||
// devices are not added.
|
// devices are not added.
|
||||||
expect(iq_stanza.outerHTML).toBe(
|
expect(iq_stanza.outerHTML).toBe(
|
||||||
@ -394,7 +461,7 @@
|
|||||||
test_utils.createContacts(_converse, 'current');
|
test_utils.createContacts(_converse, 'current');
|
||||||
const contact_jid = mock.cur_names[3].replace(/ /g,'.').toLowerCase() + '@localhost';
|
const contact_jid = mock.cur_names[3].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
|
|
||||||
test_utils.waitUntil(function () {
|
test_utils.waitUntil(() => {
|
||||||
return _.filter(
|
return _.filter(
|
||||||
_converse.connection.IQ_stanzas,
|
_converse.connection.IQ_stanzas,
|
||||||
(iq) => {
|
(iq) => {
|
||||||
@ -402,7 +469,7 @@
|
|||||||
if (node) { iq_stanza = iq.nodeTree;}
|
if (node) { iq_stanza = iq.nodeTree;}
|
||||||
return node;
|
return node;
|
||||||
}).length;
|
}).length;
|
||||||
}).then(function () {
|
}).then(() => {
|
||||||
expect(iq_stanza.outerHTML).toBe(
|
expect(iq_stanza.outerHTML).toBe(
|
||||||
'<iq type="get" from="dummy@localhost" to="dummy@localhost" xmlns="jabber:client" id="'+iq_stanza.getAttribute("id")+'">'+
|
'<iq type="get" from="dummy@localhost" to="dummy@localhost" xmlns="jabber:client" id="'+iq_stanza.getAttribute("id")+'">'+
|
||||||
'<pubsub xmlns="http://jabber.org/protocol/pubsub">'+
|
'<pubsub xmlns="http://jabber.org/protocol/pubsub">'+
|
||||||
@ -421,18 +488,49 @@
|
|||||||
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
||||||
.c('device', {'id': '555'});
|
.c('device', {'id': '555'});
|
||||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
return test_utils.waitUntil(() => _converse.omemo_store);
|
||||||
expect(_converse.devicelists.length).toBe(1);
|
|
||||||
return test_utils.waitUntil(() => _converse.devicelists);
|
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
// We simply emit, to avoid doing all the setup work
|
// We simply emit, to avoid doing all the setup work
|
||||||
expect(_converse.devicelists.length).toBe(1);
|
expect(_converse.devicelists.length).toBe(1);
|
||||||
let devicelist = _converse.devicelists.get(_converse.bare_jid);
|
const devicelist = _converse.devicelists.get(_converse.bare_jid);
|
||||||
expect(devicelist.devices.length).toBe(2);
|
expect(devicelist.devices.length).toBe(2);
|
||||||
expect(devicelist.devices.at(0).get('id')).toBe('555');
|
expect(devicelist.devices.at(0).get('id')).toBe('555');
|
||||||
expect(devicelist.devices.at(1).get('id')).toBe('123456789');
|
expect(devicelist.devices.at(1).get('id')).toBe('123456789');
|
||||||
_converse.emit('OMEMOInitialized');
|
// Check that own device was published
|
||||||
|
return test_utils.waitUntil(() => {
|
||||||
|
return _.filter(
|
||||||
|
_converse.connection.IQ_stanzas,
|
||||||
|
(iq) => {
|
||||||
|
const node = iq.nodeTree.querySelector('iq[from="'+_converse.bare_jid+'"] publish[node="eu.siacs.conversations.axolotl.devicelist"]');
|
||||||
|
if (node) { iq_stanza = iq.nodeTree;}
|
||||||
|
return node;
|
||||||
|
}).length;
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
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));
|
||||||
|
|
||||||
|
// Check that own bundle gets published
|
||||||
|
return test_utils.waitUntil(() => {
|
||||||
|
return _.filter(_converse.connection.IQ_stanzas, (iq) => {
|
||||||
|
const node = iq.nodeTree.querySelector('publish[node="eu.siacs.conversations.axolotl.bundles:123456789"]');
|
||||||
|
if (node) { iq_stanza = iq.nodeTree; }
|
||||||
|
return node;
|
||||||
|
}).length;
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
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 _converse.api.waitUntil('OMEMOInitialized');
|
||||||
|
}).then(() => {
|
||||||
let stanza = $msg({
|
let stanza = $msg({
|
||||||
'from': contact_jid,
|
'from': contact_jid,
|
||||||
'to': _converse.bare_jid,
|
'to': _converse.bare_jid,
|
||||||
@ -452,7 +550,7 @@
|
|||||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
|
||||||
expect(_converse.devicelists.length).toBe(2);
|
expect(_converse.devicelists.length).toBe(2);
|
||||||
devicelist = _converse.devicelists.get(contact_jid);
|
let devicelist = _converse.devicelists.get(contact_jid);
|
||||||
expect(devicelist.devices.length).toBe(1);
|
expect(devicelist.devices.length).toBe(1);
|
||||||
let device = devicelist.devices.at(0);
|
let device = devicelist.devices.at(0);
|
||||||
expect(device.get('bundle').identity_key).toBe('3333');
|
expect(device.get('bundle').identity_key).toBe('3333');
|
||||||
@ -543,7 +641,7 @@
|
|||||||
_converse.emit('rosterContactsFetched');
|
_converse.emit('rosterContactsFetched');
|
||||||
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
|
|
||||||
test_utils.waitUntil(function () {
|
test_utils.waitUntil(() => {
|
||||||
return _.filter(
|
return _.filter(
|
||||||
_converse.connection.IQ_stanzas,
|
_converse.connection.IQ_stanzas,
|
||||||
(iq) => {
|
(iq) => {
|
||||||
@ -551,7 +649,7 @@
|
|||||||
if (node) { iq_stanza = iq.nodeTree;}
|
if (node) { iq_stanza = iq.nodeTree;}
|
||||||
return node;
|
return node;
|
||||||
}).length;
|
}).length;
|
||||||
}).then(function () {
|
}).then(() => {
|
||||||
const stanza = $iq({
|
const stanza = $iq({
|
||||||
'from': contact_jid,
|
'from': contact_jid,
|
||||||
'id': iq_stanza.getAttribute('id'),
|
'id': iq_stanza.getAttribute('id'),
|
||||||
@ -589,14 +687,14 @@
|
|||||||
return node;
|
return node;
|
||||||
}).length;
|
}).length;
|
||||||
});
|
});
|
||||||
}).then(function () {
|
}).then(() => {
|
||||||
expect(iq_stanza.outerHTML).toBe(
|
expect(iq_stanza.outerHTML).toBe(
|
||||||
`<iq from="dummy@localhost" type="set" xmlns="jabber:client" id="${iq_stanza.getAttribute('id')}">`+
|
`<iq from="dummy@localhost" type="set" xmlns="jabber:client" id="${iq_stanza.getAttribute('id')}">`+
|
||||||
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
||||||
`<publish node="eu.siacs.conversations.axolotl.bundles:123456789">`+
|
`<publish node="eu.siacs.conversations.axolotl.bundles:123456789">`+
|
||||||
`<item>`+
|
`<item>`+
|
||||||
`<bundle xmlns="eu.siacs.conversations.axolotl">`+
|
`<bundle xmlns="eu.siacs.conversations.axolotl">`+
|
||||||
`<signedPreKeyPublic signedPreKeyId="0">${btoa('1234')}</signedPreKeyPublic>`+
|
`<signedPreKeyPublic signedPreKeyId="1">${btoa('1234')}</signedPreKeyPublic>`+
|
||||||
`<signedPreKeySignature>${btoa('11112222333344445555')}</signedPreKeySignature>`+
|
`<signedPreKeySignature>${btoa('11112222333344445555')}</signedPreKeySignature>`+
|
||||||
`<identityKey>${btoa('1234')}</identityKey>`+
|
`<identityKey>${btoa('1234')}</identityKey>`+
|
||||||
`<prekeys>`+
|
`<prekeys>`+
|
||||||
@ -646,7 +744,7 @@
|
|||||||
'</iq>');
|
'</iq>');
|
||||||
|
|
||||||
const stanza = $iq({
|
const stanza = $iq({
|
||||||
'from': contact_jid,
|
'from': _converse.bare_jid,
|
||||||
'id': iq_stanza.getAttribute('id'),
|
'id': iq_stanza.getAttribute('id'),
|
||||||
'to': _converse.bare_jid,
|
'to': _converse.bare_jid,
|
||||||
'type': 'result',
|
'type': 'result',
|
||||||
@ -656,17 +754,19 @@
|
|||||||
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
||||||
.c('device', {'id': '482886413b977930064a5888b92134fe'});
|
.c('device', {'id': '482886413b977930064a5888b92134fe'});
|
||||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
return test_utils.waitUntil(() => _converse.omemo_store);
|
||||||
|
}).then(() => {
|
||||||
expect(_converse.devicelists.length).toBe(1);
|
expect(_converse.devicelists.length).toBe(1);
|
||||||
const devicelist = _converse.devicelists.get(_converse.bare_jid);
|
const devicelist = _converse.devicelists.get(_converse.bare_jid);
|
||||||
expect(devicelist.devices.length).toBe(1);
|
expect(devicelist.devices.length).toBe(2);
|
||||||
expect(devicelist.devices.at(0).get('id')).toBe('482886413b977930064a5888b92134fe');
|
expect(devicelist.devices.at(0).get('id')).toBe('482886413b977930064a5888b92134fe');
|
||||||
|
expect(devicelist.devices.at(1).get('id')).toBe('123456789');
|
||||||
return test_utils.openChatBoxFor(_converse, contact_jid);
|
// Check that own device was published
|
||||||
}).then(() => {
|
|
||||||
return test_utils.waitUntil(() => {
|
return test_utils.waitUntil(() => {
|
||||||
return _.filter(_converse.connection.IQ_stanzas, function (iq) {
|
return _.filter(
|
||||||
const node = iq.nodeTree.querySelector('publish[node="eu.siacs.conversations.axolotl.devicelist"]');
|
_converse.connection.IQ_stanzas,
|
||||||
|
(iq) => {
|
||||||
|
const node = iq.nodeTree.querySelector('iq[from="'+_converse.bare_jid+'"] publish[node="eu.siacs.conversations.axolotl.devicelist"]');
|
||||||
if (node) { iq_stanza = iq.nodeTree;}
|
if (node) { iq_stanza = iq.nodeTree;}
|
||||||
return node;
|
return node;
|
||||||
}).length;
|
}).length;
|
||||||
@ -693,8 +793,9 @@
|
|||||||
'type': 'result'});
|
'type': 'result'});
|
||||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
|
||||||
|
// Check that own bundle gets published
|
||||||
return test_utils.waitUntil(() => {
|
return test_utils.waitUntil(() => {
|
||||||
return _.filter(_converse.connection.IQ_stanzas, function (iq) {
|
return _.filter(_converse.connection.IQ_stanzas, (iq) => {
|
||||||
const node = iq.nodeTree.querySelector('publish[node="eu.siacs.conversations.axolotl.bundles:123456789"]');
|
const node = iq.nodeTree.querySelector('publish[node="eu.siacs.conversations.axolotl.bundles:123456789"]');
|
||||||
if (node) { iq_stanza = iq.nodeTree; }
|
if (node) { iq_stanza = iq.nodeTree; }
|
||||||
return node;
|
return node;
|
||||||
@ -707,7 +808,7 @@
|
|||||||
const signed_prekeys = iq_stanza.querySelectorAll('signedPreKeyPublic');
|
const signed_prekeys = iq_stanza.querySelectorAll('signedPreKeyPublic');
|
||||||
expect(signed_prekeys.length).toBe(1);
|
expect(signed_prekeys.length).toBe(1);
|
||||||
const signed_prekey = signed_prekeys[0];
|
const signed_prekey = signed_prekeys[0];
|
||||||
expect(signed_prekey.getAttribute('signedPreKeyId')).toBe('0')
|
expect(signed_prekey.getAttribute('signedPreKeyId')).toBe('1')
|
||||||
expect(iq_stanza.querySelectorAll('signedPreKeySignature').length).toBe(1);
|
expect(iq_stanza.querySelectorAll('signedPreKeySignature').length).toBe(1);
|
||||||
expect(iq_stanza.querySelectorAll('identityKey').length).toBe(1);
|
expect(iq_stanza.querySelectorAll('identityKey').length).toBe(1);
|
||||||
|
|
||||||
@ -717,7 +818,10 @@
|
|||||||
'to': _converse.bare_jid,
|
'to': _converse.bare_jid,
|
||||||
'type': 'result'});
|
'type': 'result'});
|
||||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
return _converse.api.waitUntil('OMEMOInitialized', 1000);
|
||||||
|
}).then(() => {
|
||||||
|
return test_utils.openChatBoxFor(_converse, contact_jid);
|
||||||
|
}).then(() => {
|
||||||
return test_utils.waitUntil(() => {
|
return test_utils.waitUntil(() => {
|
||||||
return _.filter(
|
return _.filter(
|
||||||
_converse.connection.IQ_stanzas,
|
_converse.connection.IQ_stanzas,
|
||||||
@ -748,7 +852,9 @@
|
|||||||
.c('device', {'id': '4e30f35051b7b8b42abe083742187228'}).up()
|
.c('device', {'id': '4e30f35051b7b8b42abe083742187228'}).up()
|
||||||
.c('device', {'id': 'ae890ac52d0df67ed7cfdf51b644e901'});
|
.c('device', {'id': 'ae890ac52d0df67ed7cfdf51b644e901'});
|
||||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
const devicelist = _converse.devicelists.get(contact_jid);
|
||||||
|
return test_utils.waitUntil(() => devicelist.devices.length);
|
||||||
|
}).then(() => {
|
||||||
expect(_converse.devicelists.length).toBe(2);
|
expect(_converse.devicelists.length).toBe(2);
|
||||||
const devicelist = _converse.devicelists.get(contact_jid);
|
const devicelist = _converse.devicelists.get(contact_jid);
|
||||||
expect(devicelist.devices.length).toBe(4);
|
expect(devicelist.devices.length).toBe(4);
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
"<presence xmlns='jabber:client'>"+
|
"<presence xmlns='jabber:client'>"+
|
||||||
"<status>Hello world</status>"+
|
"<status>Hello world</status>"+
|
||||||
"<priority>0</priority>"+
|
"<priority>0</priority>"+
|
||||||
"<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='nE765l4CRVrSUEIPAdtgCw4+5cc='/>"+
|
"<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='ggltNSI5YG/7dFKB57Bk2dRYRU0='/>"+
|
||||||
"</presence>"
|
"</presence>"
|
||||||
);
|
);
|
||||||
_converse.priority = 2;
|
_converse.priority = 2;
|
||||||
@ -57,7 +57,7 @@
|
|||||||
"<show>away</show>"+
|
"<show>away</show>"+
|
||||||
"<status>Going jogging</status>"+
|
"<status>Going jogging</status>"+
|
||||||
"<priority>2</priority>"+
|
"<priority>2</priority>"+
|
||||||
"<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='nE765l4CRVrSUEIPAdtgCw4+5cc='/>"+
|
"<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='ggltNSI5YG/7dFKB57Bk2dRYRU0='/>"+
|
||||||
"</presence>"
|
"</presence>"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -68,7 +68,7 @@
|
|||||||
"<show>dnd</show>"+
|
"<show>dnd</show>"+
|
||||||
"<status>Doing taxes</status>"+
|
"<status>Doing taxes</status>"+
|
||||||
"<priority>0</priority>"+
|
"<priority>0</priority>"+
|
||||||
"<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='nE765l4CRVrSUEIPAdtgCw4+5cc='/>"+
|
"<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='ggltNSI5YG/7dFKB57Bk2dRYRU0='/>"+
|
||||||
"</presence>"
|
"</presence>"
|
||||||
);
|
);
|
||||||
}));
|
}));
|
||||||
@ -97,7 +97,7 @@
|
|||||||
.toBe("<presence xmlns='jabber:client'>"+
|
.toBe("<presence xmlns='jabber:client'>"+
|
||||||
"<status>My custom status</status>"+
|
"<status>My custom status</status>"+
|
||||||
"<priority>0</priority>"+
|
"<priority>0</priority>"+
|
||||||
"<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='nE765l4CRVrSUEIPAdtgCw4+5cc='/>"+
|
"<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='ggltNSI5YG/7dFKB57Bk2dRYRU0='/>"+
|
||||||
"</presence>")
|
"</presence>")
|
||||||
|
|
||||||
return test_utils.waitUntil(function () {
|
return test_utils.waitUntil(function () {
|
||||||
@ -113,7 +113,7 @@
|
|||||||
modal.el.querySelector('[type="submit"]').click();
|
modal.el.querySelector('[type="submit"]').click();
|
||||||
expect(_converse.connection.send.calls.mostRecent().args[0].toLocaleString())
|
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>"+
|
.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='nE765l4CRVrSUEIPAdtgCw4+5cc='/>"+
|
"<c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='https://conversejs.org' ver='ggltNSI5YG/7dFKB57Bk2dRYRU0='/>"+
|
||||||
"</presence>")
|
"</presence>")
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -177,7 +177,7 @@
|
|||||||
try {
|
try {
|
||||||
return sessionBuilder.processPreKey({
|
return sessionBuilder.processPreKey({
|
||||||
'registrationId': parseInt(_converse.omemo_store.get('device_id'), 10),
|
'registrationId': parseInt(_converse.omemo_store.get('device_id'), 10),
|
||||||
'identityKey': _converse.omemo_store.get('identity_keypair').pubKey,
|
'identityKey': _converse.omemo_store.get('identity_key'),
|
||||||
'signedPreKey': {
|
'signedPreKey': {
|
||||||
'keyId': bundle.signed_prekey.id, // <Number>
|
'keyId': bundle.signed_prekey.id, // <Number>
|
||||||
'publicKey': u.base64ToArrayBuffer(bundle.signed_prekey.public_key),
|
'publicKey': u.base64ToArrayBuffer(bundle.signed_prekey.public_key),
|
||||||
@ -478,16 +478,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
_converse.getDevicesForContact = function (jid) {
|
_converse.getDevicesForContact = function (jid) {
|
||||||
return new Promise((resolve, reject) => {
|
let devicelist;
|
||||||
_converse.api.waitUntil('OMEMOInitialized').then(() => {
|
return _converse.api.waitUntil('OMEMOInitialized')
|
||||||
let devicelist = _converse.devicelists.get(jid);
|
.then(() => {
|
||||||
if (_.isNil(devicelist)) {
|
devicelist = _converse.devicelists.get(jid) || _converse.devicelists.create({'jid': jid});
|
||||||
devicelist = _converse.devicelists.create({'jid': jid});
|
return devicelist.fetchDevices();
|
||||||
}
|
}).then(() => devicelist.devices);
|
||||||
devicelist.fetchDevices().then(() => resolve(devicelist.devices));
|
|
||||||
|
|
||||||
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_converse.contactHasOMEMOSupport = function (jid) {
|
_converse.contactHasOMEMOSupport = function (jid) {
|
||||||
@ -516,36 +512,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function generateBundle () {
|
|
||||||
/* The first thing that needs to happen if a client wants to
|
|
||||||
* start using OMEMO is they need to generate an IdentityKey
|
|
||||||
* and a Device ID. The IdentityKey is a Curve25519 [6]
|
|
||||||
* public/private Key pair. The Device ID is a randomly
|
|
||||||
* generated integer between 1 and 2^31 - 1.
|
|
||||||
*/
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
libsignal.KeyHelper.generateIdentityKeyPair().then((identity_keypair) => {
|
|
||||||
const data = {
|
|
||||||
'device_id': generateDeviceID(),
|
|
||||||
'identity_keypair': identity_keypair,
|
|
||||||
'prekeys': {}
|
|
||||||
};
|
|
||||||
libsignal.KeyHelper.generateSignedPreKey(identity_keypair, 1)
|
|
||||||
.then((signed_prekey) => {
|
|
||||||
_converse.omemo_store.storeSignedPreKey(signed_prekey.keyId, signed_prekey.keyPair);
|
|
||||||
data['signed_prekey'] = signed_prekey;
|
|
||||||
const key_promises = _.map(_.range(0, _converse.NUM_PREKEYS), id => libsignal.KeyHelper.generatePreKey(id));
|
|
||||||
Promise.all(key_promises).then(keys => {
|
|
||||||
_.forEach(keys, k => _converse.omemo_store.storePreKey(k.keyId, k.keyPair));
|
|
||||||
data['prekeys'] = keys;
|
|
||||||
resolve(data)
|
|
||||||
});
|
|
||||||
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
|
||||||
});
|
|
||||||
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
_converse.OMEMOStore = Backbone.Model.extend({
|
_converse.OMEMOStore = Backbone.Model.extend({
|
||||||
|
|
||||||
Direction: {
|
Direction: {
|
||||||
@ -652,19 +618,49 @@
|
|||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
generateBundle () {
|
||||||
|
/* The first thing that needs to happen if a client wants to
|
||||||
|
* start using OMEMO is they need to generate an IdentityKey
|
||||||
|
* and a Device ID. The IdentityKey is a Curve25519 [6]
|
||||||
|
* public/private Key pair. The Device ID is a randomly
|
||||||
|
* generated integer between 1 and 2^31 - 1.
|
||||||
|
*/
|
||||||
|
const data = {
|
||||||
|
'device_id': generateDeviceID()
|
||||||
|
};
|
||||||
|
return libsignal.KeyHelper.generateIdentityKeyPair()
|
||||||
|
.then(identity_keypair => {
|
||||||
|
data['identity_keypair'] = identity_keypair;
|
||||||
|
data['identity_key'] = identity_keypair.pubKey;
|
||||||
|
return libsignal.KeyHelper.generateSignedPreKey(identity_keypair, 1);
|
||||||
|
}).then(signed_prekey => {
|
||||||
|
_converse.omemo_store.storeSignedPreKey(signed_prekey.keyId, signed_prekey.keyPair);
|
||||||
|
data['signed_prekey'] = signed_prekey;
|
||||||
|
return Promise.all(_.map(_.range(0, _converse.NUM_PREKEYS), id => libsignal.KeyHelper.generatePreKey(id)));
|
||||||
|
}).then(keys => {
|
||||||
|
_.forEach(keys, k => _converse.omemo_store.storePreKey(k.keyId, k.keyPair));
|
||||||
|
data['prekeys'] = keys;
|
||||||
|
this.save(data)
|
||||||
|
// Save the bundle to the device
|
||||||
|
const devicelist = _converse.devicelists.get(_converse.bare_jid),
|
||||||
|
device = devicelist.devices.create({'id': data.device_id, 'jid': _converse.bare_jid});
|
||||||
|
device.save('bundle', data);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
fetchSession () {
|
fetchSession () {
|
||||||
if (_.isUndefined(this._setup_promise)) {
|
if (_.isUndefined(this._setup_promise)) {
|
||||||
this._setup_promise = new Promise((resolve, reject) => {
|
this._setup_promise = new Promise((resolve, reject) => {
|
||||||
this.fetch({
|
this.fetch({
|
||||||
'success': () => {
|
'success': () => {
|
||||||
if (!_converse.omemo_store.get('device_id')) {
|
if (!_converse.omemo_store.get('device_id')) {
|
||||||
generateBundle().then(data => resolve(this.save(data))).catch(resolve);
|
this.generateBundle().then(resolve).catch(resolve);
|
||||||
} else {
|
} else {
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'error': () => {
|
'error': () => {
|
||||||
generateBundle().then(data => resolve(this.save(data))).catch(resolve);
|
this.generateBundle().then(resolve).catch(resolve);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -738,13 +734,19 @@
|
|||||||
this.devices.fetch({
|
this.devices.fetch({
|
||||||
'success': (collection) => {
|
'success': (collection) => {
|
||||||
if (collection.length === 0) {
|
if (collection.length === 0) {
|
||||||
this.fetchDevicesFromServer().then(resolve).catch(reject);
|
this.fetchDevicesFromServer()
|
||||||
|
.then(ids => this.publishCurrentDevice(ids))
|
||||||
|
.then(resolve)
|
||||||
|
.catch(resolve);
|
||||||
} else {
|
} else {
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'error': () => {
|
'error': () => {
|
||||||
this.fetchDevicesFromServer().then(resolve).catch(reject);
|
this.fetchDevicesFromServer()
|
||||||
|
.then(ids => this.publishCurrentDevice(ids))
|
||||||
|
.then(resolve)
|
||||||
|
.catch(resolve)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -752,25 +754,38 @@
|
|||||||
return this._devices_promise;
|
return this._devices_promise;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
publishCurrentDevice (device_ids) {
|
||||||
|
if (this.get('jid') !== _converse.bare_jid) {
|
||||||
|
// We only publish for ourselves.
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
return restoreOMEMOSession()
|
||||||
|
.then(() => {
|
||||||
|
const device_id = _converse.omemo_store.get('device_id');
|
||||||
|
if (!_.includes(device_ids, device_id)) {
|
||||||
|
return this.publishDevices();
|
||||||
|
} else {
|
||||||
|
const own_device = this.devices.findWhere({'id': device_id})
|
||||||
|
if (!own_device.get('active')) {
|
||||||
|
own_device.set('active', true, {'silent': true});
|
||||||
|
return this.publishDevices();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
fetchDevicesFromServer () {
|
fetchDevicesFromServer () {
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const stanza = $iq({
|
const stanza = $iq({
|
||||||
'type': 'get',
|
'type': 'get',
|
||||||
'from': _converse.bare_jid,
|
'from': _converse.bare_jid,
|
||||||
'to': this.get('jid')
|
'to': this.get('jid')
|
||||||
}).c('pubsub', {'xmlns': Strophe.NS.PUBSUB})
|
}).c('pubsub', {'xmlns': Strophe.NS.PUBSUB})
|
||||||
.c('items', {'node': Strophe.NS.OMEMO_DEVICELIST});
|
.c('items', {'node': Strophe.NS.OMEMO_DEVICELIST});
|
||||||
_converse.connection.sendIQ(
|
return _converse.api.sendIQ(stanza)
|
||||||
stanza,
|
.then(iq => {
|
||||||
(iq) => {
|
const device_ids = _.map(sizzle(`list[xmlns="${Strophe.NS.OMEMO}"] device`, iq), dev => dev.getAttribute('id'));
|
||||||
_.forEach(
|
_.forEach(device_ids, id => this.devices.create({'id': id, 'jid': this.get('jid')}));
|
||||||
sizzle(`list[xmlns="${Strophe.NS.OMEMO}"] device`, iq),
|
return device_ids;
|
||||||
(dev) => this.devices.create({'id': dev.getAttribute('id'), 'jid': this.get('jid')})
|
|
||||||
);
|
|
||||||
resolve();
|
|
||||||
},
|
|
||||||
reject,
|
|
||||||
_converse.IQ_TIMEOUT);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -788,18 +803,6 @@
|
|||||||
return _converse.api.sendIQ(stanza);
|
return _converse.api.sendIQ(stanza);
|
||||||
},
|
},
|
||||||
|
|
||||||
addOwnDevice (device_id) {
|
|
||||||
/* Add this device to our list of devices stored on the
|
|
||||||
* server.
|
|
||||||
* https://xmpp.org/extensions/xep-0384.html#usecases-announcing
|
|
||||||
*/
|
|
||||||
if (this.get('jid') !== _converse.bare_jid) {
|
|
||||||
throw new Error("Cannot add device to someone else's device list");
|
|
||||||
}
|
|
||||||
this.devices.create({'id': device_id.toString(), 'jid': this.get('jid')});
|
|
||||||
return this.publishDevices();
|
|
||||||
},
|
|
||||||
|
|
||||||
removeOwnDevices (device_ids) {
|
removeOwnDevices (device_ids) {
|
||||||
if (this.get('jid') !== _converse.bare_jid) {
|
if (this.get('jid') !== _converse.bare_jid) {
|
||||||
throw new Error("Cannot remove devices from someone else's device list");
|
throw new Error("Cannot remove devices from someone else's device list");
|
||||||
@ -861,25 +864,6 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateOwnDeviceList () {
|
|
||||||
/* If our own device is not on the list, add it.
|
|
||||||
* Also, deduplicate devices if necessary.
|
|
||||||
*/
|
|
||||||
const devicelist = _converse.devicelists.get(_converse.bare_jid),
|
|
||||||
device_id = _converse.omemo_store.get('device_id').toString(),
|
|
||||||
own_device = devicelist.devices.findWhere({'id': device_id});
|
|
||||||
|
|
||||||
if (!own_device) {
|
|
||||||
return devicelist.addOwnDevice(device_id);
|
|
||||||
} else if (!own_device.get('active')) {
|
|
||||||
own_device.set('active', true, {'silent': true});
|
|
||||||
return devicelist.addOwnDevice(device_id);
|
|
||||||
} else {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function updateBundleFromStanza (stanza) {
|
function updateBundleFromStanza (stanza) {
|
||||||
const items_el = sizzle(`items`, stanza).pop();
|
const items_el = sizzle(`items`, stanza).pop();
|
||||||
if (!items_el || !items_el.getAttribute('node').startsWith(Strophe.NS.OMEMO_BUNDLES)) {
|
if (!items_el || !items_el.getAttribute('node').startsWith(Strophe.NS.OMEMO_BUNDLES)) {
|
||||||
@ -916,9 +900,11 @@
|
|||||||
devices.create({'id': device_id, 'jid': jid})
|
devices.create({'id': device_id, 'jid': jid})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (Strophe.getBareJidFromJid(jid) === _converse.bare_jid) {
|
||||||
// Make sure our own device is on the list (i.e. if it was
|
// Make sure our own device is on the list (i.e. if it was
|
||||||
// removed, add it again.
|
// removed, add it again.
|
||||||
updateOwnDeviceList();
|
_converse.devicelists.get(_converse.bare_jid).publishCurrentDevice(device_ids);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerPEPPushHandler () {
|
function registerPEPPushHandler () {
|
||||||
@ -954,13 +940,15 @@
|
|||||||
|
|
||||||
fetchOwnDevices()
|
fetchOwnDevices()
|
||||||
.then(() => restoreOMEMOSession())
|
.then(() => restoreOMEMOSession())
|
||||||
.then(() => updateOwnDeviceList())
|
|
||||||
.then(() => _converse.omemo.publishBundle())
|
.then(() => _converse.omemo.publishBundle())
|
||||||
.then(() => _converse.emit('OMEMOInitialized'))
|
.then(() => _converse.emit('OMEMOInitialized'))
|
||||||
.catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
.catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
_converse.api.listen.on('afterTearDown', () => _converse.devicelists.reset());
|
_converse.api.listen.on('afterTearDown', () => {
|
||||||
|
_converse.devicelists.reset();
|
||||||
|
delete _converse.omemo_store;
|
||||||
|
});
|
||||||
_converse.api.listen.on('connected', registerPEPPushHandler);
|
_converse.api.listen.on('connected', registerPEPPushHandler);
|
||||||
_converse.api.listen.on('renderToolbar', (view) => view.renderOMEMOToolbarButton());
|
_converse.api.listen.on('renderToolbar', (view) => view.renderOMEMOToolbarButton());
|
||||||
_converse.api.listen.on('statusInitialized', initOMEMO);
|
_converse.api.listen.on('statusInitialized', initOMEMO);
|
||||||
|
@ -100,7 +100,7 @@
|
|||||||
|
|
||||||
utils.openChatBoxFor = function (_converse, jid) {
|
utils.openChatBoxFor = function (_converse, jid) {
|
||||||
_converse.roster.get(jid).trigger("open");
|
_converse.roster.get(jid).trigger("open");
|
||||||
return utils.waitUntil(() => _converse.chatboxviews.get(jid));
|
return utils.waitUntil(() => _converse.chatboxviews.get(jid), 1000);
|
||||||
};
|
};
|
||||||
|
|
||||||
utils.openChatRoomViaModal = function (_converse, jid, nick='') {
|
utils.openChatRoomViaModal = function (_converse, jid, nick='') {
|
||||||
|
Loading…
Reference in New Issue
Block a user