2018-05-12 19:37:44 +02:00
|
|
|
|
(function (root, factory) {
|
2018-06-30 23:03:36 +02:00
|
|
|
|
define(["jasmine", "mock", "test-utils"], factory);
|
|
|
|
|
} (this, function (jasmine, mock, test_utils) {
|
2018-12-13 09:48:43 +01:00
|
|
|
|
const { $iq, $pres, $msg, _, Strophe } = converse.env;
|
|
|
|
|
const u = converse.env.utils;
|
2018-05-12 19:37:44 +02:00
|
|
|
|
|
2018-08-26 19:33:34 +02:00
|
|
|
|
|
2019-02-01 15:22:45 +01:00
|
|
|
|
async function deviceListFetched (_converse, jid) {
|
2019-07-11 22:50:30 +02:00
|
|
|
|
const stanza = await u.waitUntil(() => _.filter(
|
2018-08-26 19:33:34 +02:00
|
|
|
|
_converse.connection.IQ_stanzas,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
iq => iq.querySelector(`iq[to="${jid}"] items[node="eu.siacs.conversations.axolotl.devicelist"]`)
|
2019-02-01 15:22:45 +01:00
|
|
|
|
).pop());
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => _converse.devicelists.get(jid));
|
2019-02-01 15:22:45 +01:00
|
|
|
|
return stanza;
|
2018-08-26 19:33:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function ownDeviceHasBeenPublished (_converse) {
|
2018-09-25 14:05:56 +02:00
|
|
|
|
return _.filter(
|
2018-08-26 19:33:34 +02:00
|
|
|
|
_converse.connection.IQ_stanzas,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
iq => iq.querySelector('iq[from="'+_converse.bare_jid+'"] publish[node="eu.siacs.conversations.axolotl.devicelist"]')
|
2018-09-25 14:05:56 +02:00
|
|
|
|
).pop();
|
2018-08-26 19:33:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function bundleHasBeenPublished (_converse) {
|
2018-09-25 14:05:56 +02:00
|
|
|
|
return _.filter(
|
2018-08-26 19:33:34 +02:00
|
|
|
|
_converse.connection.IQ_stanzas,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
iq => iq.querySelector('publish[node="eu.siacs.conversations.axolotl.bundles:123456789"]')
|
2018-09-25 14:05:56 +02:00
|
|
|
|
).pop();
|
2018-08-26 19:33:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function bundleFetched (_converse, jid, device_id) {
|
2018-09-25 14:05:56 +02:00
|
|
|
|
return _.filter(
|
2018-08-26 19:33:34 +02:00
|
|
|
|
_converse.connection.IQ_stanzas,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
iq => iq.querySelector(`iq[to="${jid}"] items[node="eu.siacs.conversations.axolotl.bundles:${device_id}"]`)
|
2018-09-25 14:05:56 +02:00
|
|
|
|
).pop();
|
2018-08-26 19:33:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-15 23:18:06 +02:00
|
|
|
|
async function initializedOMEMO (_converse) {
|
2018-12-19 08:14:58 +01:00
|
|
|
|
await test_utils.waitUntilDiscoConfirmed(
|
|
|
|
|
_converse, _converse.bare_jid,
|
|
|
|
|
[{'category': 'pubsub', 'type': 'pep'}],
|
|
|
|
|
['http://jabber.org/protocol/pubsub#publish-options']
|
|
|
|
|
);
|
2019-07-11 22:50:30 +02:00
|
|
|
|
let iq_stanza = await u.waitUntil(() => deviceListFetched(_converse, _converse.bare_jid));
|
2018-10-15 23:18:06 +02:00
|
|
|
|
let stanza = $iq({
|
|
|
|
|
'from': _converse.bare_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {'xmlns': "http://jabber.org/protocol/pubsub"})
|
|
|
|
|
.c('items', {'node': "eu.siacs.conversations.axolotl.devicelist"})
|
|
|
|
|
.c('item', {'xmlns': "http://jabber.org/protocol/pubsub"}) // TODO: must have an id attribute
|
|
|
|
|
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
|
|
|
|
.c('device', {'id': '482886413b977930064a5888b92134fe'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => ownDeviceHasBeenPublished(_converse))
|
2018-10-15 23:18:06 +02:00
|
|
|
|
|
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': _converse.bare_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => bundleHasBeenPublished(_converse))
|
2018-10-15 23:18:06 +02:00
|
|
|
|
|
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': _converse.bare_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
await _converse.api.waitUntil('OMEMOInitialized');
|
2018-08-27 14:25:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-26 19:33:34 +02:00
|
|
|
|
|
2018-05-12 19:37:44 +02:00
|
|
|
|
describe("The OMEMO module", function() {
|
|
|
|
|
|
2018-08-04 19:41:06 +02:00
|
|
|
|
it("adds methods for encrypting and decrypting messages via AES GCM",
|
2019-02-12 14:21:45 +01:00
|
|
|
|
mock.initConverse(
|
2018-10-15 23:18:06 +02:00
|
|
|
|
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
|
|
|
|
async function (done, _converse) {
|
2018-08-04 19:41:06 +02:00
|
|
|
|
|
2018-08-04 20:20:05 +02:00
|
|
|
|
const message = 'This message will be encrypted'
|
2018-08-04 19:41:06 +02:00
|
|
|
|
test_utils.createContacts(_converse, 'current', 1);
|
2019-03-29 21:10:45 +01:00
|
|
|
|
_converse.api.trigger('rosterContactsFetched');
|
2019-06-03 07:58:51 +02:00
|
|
|
|
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
2018-10-15 23:18:06 +02:00
|
|
|
|
const view = await test_utils.openChatBoxFor(_converse, contact_jid);
|
|
|
|
|
const payload = await view.model.encryptMessage(message);
|
|
|
|
|
const result = await view.model.decryptMessage(payload);
|
|
|
|
|
expect(result).toBe(message);
|
|
|
|
|
done();
|
2018-08-04 19:41:06 +02:00
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
2018-07-28 16:36:23 +02:00
|
|
|
|
it("enables encrypted messages to be sent and received",
|
2019-02-12 14:21:45 +01:00
|
|
|
|
mock.initConverse(
|
2019-07-11 12:30:51 +02:00
|
|
|
|
null, ['rosterGroupsFetched', 'chatBoxesFetched', 'emojisInitialized'], {},
|
2018-10-15 23:18:06 +02:00
|
|
|
|
async function (done, _converse) {
|
2018-07-25 12:59:12 +02:00
|
|
|
|
|
2018-10-15 23:18:06 +02:00
|
|
|
|
let sent_stanza;
|
2018-07-25 12:59:12 +02:00
|
|
|
|
test_utils.createContacts(_converse, 'current', 1);
|
2019-03-29 21:10:45 +01:00
|
|
|
|
_converse.api.trigger('rosterContactsFetched');
|
2019-06-03 07:58:51 +02:00
|
|
|
|
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => initializedOMEMO(_converse));
|
2018-10-15 23:18:06 +02:00
|
|
|
|
await test_utils.openChatBoxFor(_converse, contact_jid);
|
2019-07-11 22:50:30 +02:00
|
|
|
|
let iq_stanza = await u.waitUntil(() => deviceListFetched(_converse, contact_jid));
|
2018-10-15 23:18:06 +02:00
|
|
|
|
let stanza = $iq({
|
2018-07-25 12:59:12 +02:00
|
|
|
|
'from': contact_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-08-18 18:26:41 +02:00
|
|
|
|
'to': _converse.connection.jid,
|
2018-07-25 12:59:12 +02:00
|
|
|
|
'type': 'result',
|
2018-08-18 18:26:41 +02:00
|
|
|
|
}).c('pubsub', {'xmlns': "http://jabber.org/protocol/pubsub"})
|
|
|
|
|
.c('items', {'node': "eu.siacs.conversations.axolotl.devicelist"})
|
|
|
|
|
.c('item', {'xmlns': "http://jabber.org/protocol/pubsub"}) // TODO: must have an id attribute
|
|
|
|
|
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
|
|
|
|
.c('device', {'id': '555'});
|
2018-10-15 23:18:06 +02:00
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => _converse.omemo_store);
|
2018-10-15 23:18:06 +02:00
|
|
|
|
const devicelist = _converse.devicelists.get({'jid': contact_jid});
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => devicelist.devices.length === 1);
|
2018-10-15 23:18:06 +02:00
|
|
|
|
|
|
|
|
|
const view = _converse.chatboxviews.get(contact_jid);
|
|
|
|
|
view.model.set('omemo_active', true);
|
|
|
|
|
|
|
|
|
|
const textarea = view.el.querySelector('.chat-textarea');
|
|
|
|
|
textarea.value = 'This message will be encrypted';
|
2019-05-26 10:58:52 +02:00
|
|
|
|
view.onKeyDown({
|
2018-10-15 23:18:06 +02:00
|
|
|
|
target: textarea,
|
2019-08-05 11:14:49 +02:00
|
|
|
|
preventDefault: function preventDefault () {},
|
2018-10-15 23:18:06 +02:00
|
|
|
|
keyCode: 13 // Enter
|
|
|
|
|
});
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => bundleFetched(_converse, contact_jid, '555'));
|
2018-10-15 23:18:06 +02:00
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': contact_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {
|
|
|
|
|
'xmlns': 'http://jabber.org/protocol/pubsub'
|
|
|
|
|
}).c('items', {'node': "eu.siacs.conversations.axolotl.bundles:555"})
|
|
|
|
|
.c('item')
|
|
|
|
|
.c('bundle', {'xmlns': 'eu.siacs.conversations.axolotl'})
|
|
|
|
|
.c('signedPreKeyPublic', {'signedPreKeyId': '4223'}).t(btoa('1111')).up()
|
|
|
|
|
.c('signedPreKeySignature').t(btoa('2222')).up()
|
|
|
|
|
.c('identityKey').t(btoa('3333')).up()
|
|
|
|
|
.c('prekeys')
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '1'}).t(btoa('1001')).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '2'}).t(btoa('1002')).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '3'}).t(btoa('1003'));
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => bundleFetched(_converse, _converse.bare_jid, '482886413b977930064a5888b92134fe'));
|
2018-10-15 23:18:06 +02:00
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': _converse.bare_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {
|
|
|
|
|
'xmlns': 'http://jabber.org/protocol/pubsub'
|
|
|
|
|
}).c('items', {'node': "eu.siacs.conversations.axolotl.bundles:482886413b977930064a5888b92134fe"})
|
|
|
|
|
.c('item')
|
|
|
|
|
.c('bundle', {'xmlns': 'eu.siacs.conversations.axolotl'})
|
|
|
|
|
.c('signedPreKeyPublic', {'signedPreKeyId': '4223'}).t(btoa('100000')).up()
|
|
|
|
|
.c('signedPreKeySignature').t(btoa('200000')).up()
|
|
|
|
|
.c('identityKey').t(btoa('300000')).up()
|
|
|
|
|
.c('prekeys')
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '1'}).t(btoa('1991')).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '2'}).t(btoa('1992')).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '3'}).t(btoa('1993'));
|
|
|
|
|
|
|
|
|
|
spyOn(_converse.connection, 'send').and.callFake(stanza => { sent_stanza = stanza });
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => sent_stanza);
|
2018-10-15 23:18:06 +02:00
|
|
|
|
expect(sent_stanza.toLocaleString()).toBe(
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`<message from="romeo@montague.lit/orchard" id="${sent_stanza.nodeTree.getAttribute("id")}" `+
|
|
|
|
|
`to="mercutio@montague.lit" `+
|
2018-10-15 23:18:06 +02:00
|
|
|
|
`type="chat" xmlns="jabber:client">`+
|
|
|
|
|
`<body>This is an OMEMO encrypted message which your client doesn’t seem to support. Find more information on https://conversations.im/omemo</body>`+
|
2018-11-03 14:37:57 +01:00
|
|
|
|
`<request xmlns="urn:xmpp:receipts"/>`+
|
2018-10-15 23:18:06 +02:00
|
|
|
|
`<encrypted xmlns="eu.siacs.conversations.axolotl">`+
|
|
|
|
|
`<header sid="123456789">`+
|
|
|
|
|
`<key rid="482886413b977930064a5888b92134fe">YzFwaDNSNzNYNw==</key>`+
|
|
|
|
|
`<key rid="555">YzFwaDNSNzNYNw==</key>`+
|
|
|
|
|
`<iv>${sent_stanza.nodeTree.querySelector("iv").textContent}</iv>`+
|
|
|
|
|
`</header>`+
|
|
|
|
|
`<payload>${sent_stanza.nodeTree.querySelector("payload").textContent}</payload>`+
|
|
|
|
|
`</encrypted>`+
|
|
|
|
|
`<store xmlns="urn:xmpp:hints"/>`+
|
|
|
|
|
`</message>`);
|
2018-10-15 23:47:22 +02:00
|
|
|
|
|
2018-10-15 23:18:06 +02:00
|
|
|
|
// Test reception of an encrypted message
|
2018-10-15 23:47:22 +02:00
|
|
|
|
let obj = await view.model.encryptMessage('This is an encrypted message from the contact')
|
2018-10-15 23:18:06 +02:00
|
|
|
|
// XXX: Normally the key will be encrypted via libsignal.
|
|
|
|
|
// However, we're mocking libsignal in the tests, so we include
|
|
|
|
|
// it as plaintext in the message.
|
|
|
|
|
stanza = $msg({
|
2018-07-25 12:59:12 +02:00
|
|
|
|
'from': contact_jid,
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.connection.jid,
|
|
|
|
|
'type': 'chat',
|
2018-10-15 23:47:22 +02:00
|
|
|
|
'id': _converse.connection.getUniqueId()
|
2018-10-15 23:18:06 +02:00
|
|
|
|
}).c('body').t('This is a fallback message').up()
|
|
|
|
|
.c('encrypted', {'xmlns': Strophe.NS.OMEMO})
|
|
|
|
|
.c('header', {'sid': '555'})
|
|
|
|
|
.c('key', {'rid': _converse.omemo_store.get('device_id')}).t(u.arrayBufferToBase64(obj.key_and_tag)).up()
|
|
|
|
|
.c('iv').t(obj.iv)
|
|
|
|
|
.up().up()
|
|
|
|
|
.c('payload').t(obj.payload);
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2018-10-15 23:47:22 +02:00
|
|
|
|
await new Promise((resolve, reject) => view.once('messageInserted', resolve));
|
2018-10-15 23:18:06 +02:00
|
|
|
|
expect(view.model.messages.length).toBe(2);
|
2019-06-19 11:04:09 +02:00
|
|
|
|
expect(view.el.querySelectorAll('.chat-msg__body')[1].textContent.trim())
|
2018-10-15 23:18:06 +02:00
|
|
|
|
.toBe('This is an encrypted message from the contact');
|
2018-10-15 23:47:22 +02:00
|
|
|
|
|
|
|
|
|
// #1193 Check for a received message without <body> tag
|
|
|
|
|
obj = await view.model.encryptMessage('Another received encrypted message without fallback')
|
|
|
|
|
stanza = $msg({
|
|
|
|
|
'from': contact_jid,
|
|
|
|
|
'to': _converse.connection.jid,
|
|
|
|
|
'type': 'chat',
|
|
|
|
|
'id': _converse.connection.getUniqueId()
|
|
|
|
|
}).c('encrypted', {'xmlns': Strophe.NS.OMEMO})
|
|
|
|
|
.c('header', {'sid': '555'})
|
|
|
|
|
.c('key', {'rid': _converse.omemo_store.get('device_id')}).t(u.arrayBufferToBase64(obj.key_and_tag)).up()
|
|
|
|
|
.c('iv').t(obj.iv)
|
|
|
|
|
.up().up()
|
|
|
|
|
.c('payload').t(obj.payload);
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
await new Promise((resolve, reject) => view.once('messageInserted', resolve));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => view.model.messages.length > 1);
|
2018-10-15 23:47:22 +02:00
|
|
|
|
expect(view.model.messages.length).toBe(3);
|
2019-06-19 11:04:09 +02:00
|
|
|
|
expect(view.el.querySelectorAll('.chat-msg__body')[2].textContent.trim())
|
2018-10-15 23:47:22 +02:00
|
|
|
|
.toBe('Another received encrypted message without fallback');
|
2018-10-15 23:18:06 +02:00
|
|
|
|
done();
|
2018-07-25 12:59:12 +02:00
|
|
|
|
}));
|
|
|
|
|
|
2018-12-18 11:21:04 +01:00
|
|
|
|
it("enables encrypted groupchat messages to be sent and received",
|
2019-02-12 14:21:45 +01:00
|
|
|
|
mock.initConverse(
|
2018-12-18 11:21:04 +01:00
|
|
|
|
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
|
|
|
|
async function (done, _converse) {
|
|
|
|
|
|
|
|
|
|
// MEMO encryption works only in members only conferences
|
|
|
|
|
// that are non-anonymous.
|
|
|
|
|
const features = [
|
|
|
|
|
'http://jabber.org/protocol/muc',
|
|
|
|
|
'jabber:iq:register',
|
|
|
|
|
'muc_passwordprotected',
|
|
|
|
|
'muc_hidden',
|
|
|
|
|
'muc_temporary',
|
|
|
|
|
'muc_membersonly',
|
|
|
|
|
'muc_unmoderated',
|
|
|
|
|
'muc_nonanonymous'
|
|
|
|
|
];
|
2019-07-03 14:18:46 +02:00
|
|
|
|
await test_utils.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo', features);
|
2019-06-03 07:58:51 +02:00
|
|
|
|
const view = _converse.chatboxviews.get('lounge@montague.lit');
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => initializedOMEMO(_converse));
|
2018-12-18 11:21:04 +01:00
|
|
|
|
|
|
|
|
|
const toolbar = view.el.querySelector('.chat-toolbar');
|
|
|
|
|
let toggle = toolbar.querySelector('.toggle-omemo');
|
|
|
|
|
toggle.click();
|
|
|
|
|
expect(view.model.get('omemo_active')).toBe(true);
|
|
|
|
|
|
2019-03-29 23:07:45 +01:00
|
|
|
|
// newguy enters the room
|
2019-06-03 07:58:51 +02:00
|
|
|
|
const contact_jid = 'newguy@montague.lit';
|
2018-12-18 11:21:04 +01:00
|
|
|
|
let stanza = $pres({
|
2019-06-03 07:58:51 +02:00
|
|
|
|
'to': 'romeo@montague.lit/orchard',
|
|
|
|
|
'from': 'lounge@montague.lit/newguy'
|
2018-12-18 11:21:04 +01:00
|
|
|
|
})
|
|
|
|
|
.c('x', {xmlns: Strophe.NS.MUC_USER})
|
|
|
|
|
.c('item', {
|
|
|
|
|
'affiliation': 'none',
|
2019-06-03 07:58:51 +02:00
|
|
|
|
'jid': 'newguy@montague.lit/_converse.js-290929789',
|
2018-12-18 11:21:04 +01:00
|
|
|
|
'role': 'participant'
|
|
|
|
|
}).tree();
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
|
2019-03-29 23:07:45 +01:00
|
|
|
|
// Wait for Converse to fetch newguy's device list
|
2019-07-11 22:50:30 +02:00
|
|
|
|
let iq_stanza = await u.waitUntil(() => deviceListFetched(_converse, contact_jid));
|
2019-05-20 12:38:33 +02:00
|
|
|
|
expect(Strophe.serialize(iq_stanza)).toBe(
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`<iq from="romeo@montague.lit" id="${iq_stanza.getAttribute("id")}" to="${contact_jid}" type="get" xmlns="jabber:client">`+
|
2018-12-18 11:21:04 +01:00
|
|
|
|
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
|
|
|
|
`<items node="eu.siacs.conversations.axolotl.devicelist"/>`+
|
|
|
|
|
`</pubsub>`+
|
|
|
|
|
`</iq>`);
|
|
|
|
|
|
2019-03-29 23:07:45 +01:00
|
|
|
|
// The server returns his device list
|
2018-12-18 11:21:04 +01:00
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': contact_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-12-18 11:21:04 +01:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {'xmlns': "http://jabber.org/protocol/pubsub"})
|
|
|
|
|
.c('items', {'node': "eu.siacs.conversations.axolotl.devicelist"})
|
|
|
|
|
.c('item', {'xmlns': "http://jabber.org/protocol/pubsub"}) // TODO: must have an id attribute
|
|
|
|
|
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
|
|
|
|
.c('device', {'id': '4e30f35051b7b8b42abe083742187228'}).up()
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => _converse.omemo_store);
|
2018-12-18 11:21:04 +01:00
|
|
|
|
expect(_converse.devicelists.length).toBe(2);
|
|
|
|
|
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => deviceListFetched(_converse, contact_jid));
|
2018-12-18 11:21:04 +01:00
|
|
|
|
const devicelist = _converse.devicelists.get(contact_jid);
|
|
|
|
|
expect(devicelist.devices.length).toBe(1);
|
|
|
|
|
expect(devicelist.devices.at(0).get('id')).toBe('4e30f35051b7b8b42abe083742187228');
|
|
|
|
|
|
|
|
|
|
toggle = toolbar.querySelector('.toggle-omemo');
|
|
|
|
|
expect(view.model.get('omemo_active')).toBe(true);
|
|
|
|
|
expect(u.hasClass('fa-unlock', toggle)).toBe(false);
|
|
|
|
|
expect(u.hasClass('fa-lock', toggle)).toBe(true);
|
|
|
|
|
|
|
|
|
|
const textarea = view.el.querySelector('.chat-textarea');
|
|
|
|
|
textarea.value = 'This message will be encrypted';
|
2019-05-26 10:58:52 +02:00
|
|
|
|
view.onKeyDown({
|
2018-12-18 11:21:04 +01:00
|
|
|
|
target: textarea,
|
2019-08-05 11:14:49 +02:00
|
|
|
|
preventDefault: function preventDefault () {},
|
2018-12-18 11:21:04 +01:00
|
|
|
|
keyCode: 13 // Enter
|
|
|
|
|
});
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => bundleFetched(_converse, contact_jid, '4e30f35051b7b8b42abe083742187228'), 1000);
|
2019-01-03 10:57:14 +01:00
|
|
|
|
console.log("Bundle fetched 4e30f35051b7b8b42abe083742187228");
|
2018-12-18 11:21:04 +01:00
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': contact_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-12-18 11:21:04 +01:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {
|
|
|
|
|
'xmlns': 'http://jabber.org/protocol/pubsub'
|
|
|
|
|
}).c('items', {'node': "eu.siacs.conversations.axolotl.bundles:4e30f35051b7b8b42abe083742187228"})
|
|
|
|
|
.c('item')
|
|
|
|
|
.c('bundle', {'xmlns': 'eu.siacs.conversations.axolotl'})
|
|
|
|
|
.c('signedPreKeyPublic', {'signedPreKeyId': '4223'}).t(btoa('1111')).up()
|
|
|
|
|
.c('signedPreKeySignature').t(btoa('2222')).up()
|
|
|
|
|
.c('identityKey').t(btoa('3333')).up()
|
|
|
|
|
.c('prekeys')
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '1'}).t(btoa('1001')).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '2'}).t(btoa('1002')).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '3'}).t(btoa('1003'));
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => bundleFetched(_converse, _converse.bare_jid, '482886413b977930064a5888b92134fe'), 1000);
|
2019-01-03 10:57:14 +01:00
|
|
|
|
console.log("Bundle fetched 482886413b977930064a5888b92134fe");
|
2018-12-18 11:21:04 +01:00
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': _converse.bare_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-12-18 11:21:04 +01:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {
|
|
|
|
|
'xmlns': 'http://jabber.org/protocol/pubsub'
|
|
|
|
|
}).c('items', {'node': "eu.siacs.conversations.axolotl.bundles:482886413b977930064a5888b92134fe"})
|
|
|
|
|
.c('item')
|
|
|
|
|
.c('bundle', {'xmlns': 'eu.siacs.conversations.axolotl'})
|
|
|
|
|
.c('signedPreKeyPublic', {'signedPreKeyId': '4223'}).t(btoa('100000')).up()
|
|
|
|
|
.c('signedPreKeySignature').t(btoa('200000')).up()
|
|
|
|
|
.c('identityKey').t(btoa('300000')).up()
|
|
|
|
|
.c('prekeys')
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '1'}).t(btoa('1991')).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '2'}).t(btoa('1992')).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '3'}).t(btoa('1993'));
|
|
|
|
|
|
|
|
|
|
spyOn(_converse.connection, 'send');
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => _converse.connection.send.calls.count(), 1000);
|
2018-12-18 11:21:04 +01:00
|
|
|
|
const sent_stanza = _converse.connection.send.calls.all()[0].args[0];
|
|
|
|
|
|
|
|
|
|
expect(Strophe.serialize(sent_stanza)).toBe(
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`<message from="romeo@montague.lit/orchard" `+
|
2018-12-18 11:21:04 +01:00
|
|
|
|
`id="${sent_stanza.nodeTree.getAttribute("id")}" `+
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`to="lounge@montague.lit" `+
|
2018-12-18 11:21:04 +01:00
|
|
|
|
`type="groupchat" `+
|
|
|
|
|
`xmlns="jabber:client">`+
|
|
|
|
|
`<body>This is an OMEMO encrypted message which your client doesn’t seem to support. Find more information on https://conversations.im/omemo</body>`+
|
|
|
|
|
`<encrypted xmlns="eu.siacs.conversations.axolotl">`+
|
|
|
|
|
`<header sid="123456789">`+
|
|
|
|
|
`<key rid="482886413b977930064a5888b92134fe">YzFwaDNSNzNYNw==</key>`+
|
|
|
|
|
`<key rid="4e30f35051b7b8b42abe083742187228">YzFwaDNSNzNYNw==</key>`+
|
|
|
|
|
`<iv>${sent_stanza.nodeTree.querySelector("iv").textContent}</iv>`+
|
|
|
|
|
`</header>`+
|
|
|
|
|
`<payload>${sent_stanza.nodeTree.querySelector("payload").textContent}</payload>`+
|
|
|
|
|
`</encrypted>`+
|
|
|
|
|
`<store xmlns="urn:xmpp:hints"/>`+
|
|
|
|
|
`</message>`);
|
|
|
|
|
done();
|
|
|
|
|
}));
|
|
|
|
|
|
2019-03-31 19:36:04 +02:00
|
|
|
|
it("will create a new device based on a received carbon message",
|
|
|
|
|
mock.initConverse(
|
|
|
|
|
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
|
|
|
|
async function (done, _converse) {
|
|
|
|
|
|
|
|
|
|
await test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, [], [Strophe.NS.SID]);
|
|
|
|
|
|
|
|
|
|
let sent_stanza;
|
|
|
|
|
test_utils.createContacts(_converse, 'current', 1);
|
|
|
|
|
_converse.api.trigger('rosterContactsFetched');
|
2019-06-03 07:58:51 +02:00
|
|
|
|
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => initializedOMEMO(_converse));
|
2019-03-31 19:36:04 +02:00
|
|
|
|
await test_utils.openChatBoxFor(_converse, contact_jid);
|
2019-07-11 22:50:30 +02:00
|
|
|
|
let iq_stanza = await u.waitUntil(() => deviceListFetched(_converse, contact_jid));
|
2019-03-31 19:36:04 +02:00
|
|
|
|
const stanza = $iq({
|
|
|
|
|
'from': contact_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2019-03-31 19:36:04 +02:00
|
|
|
|
'to': _converse.connection.jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {'xmlns': "http://jabber.org/protocol/pubsub"})
|
|
|
|
|
.c('items', {'node': "eu.siacs.conversations.axolotl.devicelist"})
|
|
|
|
|
.c('item', {'xmlns': "http://jabber.org/protocol/pubsub"}) // TODO: must have an id attribute
|
|
|
|
|
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
|
|
|
|
.c('device', {'id': '555'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => _converse.omemo_store);
|
2019-03-31 19:36:04 +02:00
|
|
|
|
const devicelist = _converse.devicelists.get({'jid': contact_jid});
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => devicelist.devices.length === 1);
|
2019-03-31 19:36:04 +02:00
|
|
|
|
|
|
|
|
|
const view = _converse.chatboxviews.get(contact_jid);
|
|
|
|
|
view.model.set('omemo_active', true);
|
|
|
|
|
|
|
|
|
|
// Test reception of an encrypted carbon message
|
|
|
|
|
const obj = await view.model.encryptMessage('This is an encrypted carbon message from another device of mine')
|
|
|
|
|
const carbon = u.toStanza(`
|
2019-06-03 07:58:51 +02:00
|
|
|
|
<message xmlns="jabber:client" to="romeo@montague.lit/orchard" from="romeo@montague.lit" type="chat">
|
2019-03-31 19:36:04 +02:00
|
|
|
|
<sent xmlns="urn:xmpp:carbons:2">
|
|
|
|
|
<forwarded xmlns="urn:xmpp:forward:0">
|
|
|
|
|
<message xmlns="jabber:client"
|
2019-06-03 07:58:51 +02:00
|
|
|
|
from="romeo@montague.lit/gajim.HE02SW1L"
|
2019-03-31 19:36:04 +02:00
|
|
|
|
xml:lang="en"
|
|
|
|
|
to="${contact_jid}/gajim.0LATM5V2"
|
|
|
|
|
type="chat" id="87141781-61d6-4eb3-9a31-429935a61b76">
|
|
|
|
|
|
2019-06-03 07:58:51 +02:00
|
|
|
|
<archived xmlns="urn:xmpp:mam:tmp" by="romeo@montague.lit" id="1554033877043470"/>
|
|
|
|
|
<stanza-id xmlns="urn:xmpp:sid:0" by="romeo@montague.lit" id="1554033877043470"/>
|
2019-03-31 19:36:04 +02:00
|
|
|
|
<request xmlns="urn:xmpp:receipts"/>
|
|
|
|
|
<active xmlns="http://jabber.org/protocol/chatstates"/>
|
|
|
|
|
<origin-id xmlns="urn:xmpp:sid:0" id="87141781-61d6-4eb3-9a31-429935a61b76"/>
|
|
|
|
|
<encrypted xmlns="eu.siacs.conversations.axolotl">
|
|
|
|
|
<header sid="988349631">
|
|
|
|
|
<key rid="${_converse.omemo_store.get('device_id')}"
|
|
|
|
|
prekey="true">${u.arrayBufferToBase64(obj.key_and_tag)}</key>
|
|
|
|
|
<iv>${obj.iv}</iv>
|
|
|
|
|
</header>
|
|
|
|
|
<payload>${obj.payload}</payload>
|
|
|
|
|
</encrypted>
|
|
|
|
|
<encryption xmlns="urn:xmpp:eme:0" namespace="eu.siacs.conversations.axolotl" name="OMEMO"/>
|
|
|
|
|
<store xmlns="urn:xmpp:hints"/>
|
|
|
|
|
</message>
|
|
|
|
|
</forwarded>
|
|
|
|
|
</sent>
|
|
|
|
|
</message>
|
|
|
|
|
`);
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(carbon));
|
|
|
|
|
await new Promise(resolve => view.once('messageInserted', resolve));
|
|
|
|
|
expect(view.model.messages.length).toBe(1);
|
|
|
|
|
expect(view.el.querySelector('.chat-msg__body').textContent.trim())
|
|
|
|
|
.toBe('This is an encrypted carbon message from another device of mine');
|
|
|
|
|
|
|
|
|
|
expect(devicelist.devices.length).toBe(2);
|
|
|
|
|
expect(devicelist.devices.at(0).get('id')).toBe('555');
|
|
|
|
|
expect(devicelist.devices.at(1).get('id')).toBe('988349631');
|
|
|
|
|
expect(devicelist.devices.get('988349631').get('active')).toBe(true);
|
|
|
|
|
|
|
|
|
|
const textarea = view.el.querySelector('.chat-textarea');
|
|
|
|
|
textarea.value = 'This is an encrypted message from this device';
|
2019-05-26 10:58:52 +02:00
|
|
|
|
view.onKeyDown({
|
2019-03-31 19:36:04 +02:00
|
|
|
|
target: textarea,
|
2019-08-05 11:14:49 +02:00
|
|
|
|
preventDefault: function preventDefault () {},
|
2019-03-31 19:36:04 +02:00
|
|
|
|
keyCode: 13 // Enter
|
|
|
|
|
});
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => bundleFetched(_converse, _converse.bare_jid, '988349631'));
|
2019-05-20 12:38:33 +02:00
|
|
|
|
expect(Strophe.serialize(iq_stanza)).toBe(
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`<iq from="romeo@montague.lit" id="${iq_stanza.getAttribute("id")}" to="${_converse.bare_jid}" type="get" xmlns="jabber:client">`+
|
2019-03-31 19:36:04 +02:00
|
|
|
|
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
|
|
|
|
`<items node="eu.siacs.conversations.axolotl.bundles:988349631"/>`+
|
|
|
|
|
`</pubsub>`+
|
|
|
|
|
`</iq>`);
|
|
|
|
|
done();
|
|
|
|
|
}));
|
|
|
|
|
|
2018-12-19 17:18:36 +01:00
|
|
|
|
it("gracefully handles auth errors when trying to send encrypted groupchat messages",
|
2019-02-12 14:21:45 +01:00
|
|
|
|
mock.initConverse(
|
2018-12-19 17:18:36 +01:00
|
|
|
|
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
|
|
|
|
async function (done, _converse) {
|
|
|
|
|
|
|
|
|
|
// MEMO encryption works only in members only conferences
|
|
|
|
|
// that are non-anonymous.
|
|
|
|
|
const features = [
|
|
|
|
|
'http://jabber.org/protocol/muc',
|
|
|
|
|
'jabber:iq:register',
|
|
|
|
|
'muc_passwordprotected',
|
|
|
|
|
'muc_hidden',
|
|
|
|
|
'muc_temporary',
|
|
|
|
|
'muc_membersonly',
|
|
|
|
|
'muc_unmoderated',
|
|
|
|
|
'muc_nonanonymous'
|
|
|
|
|
];
|
2019-07-03 14:18:46 +02:00
|
|
|
|
await test_utils.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo', features);
|
2019-06-03 07:58:51 +02:00
|
|
|
|
const view = _converse.chatboxviews.get('lounge@montague.lit');
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => initializedOMEMO(_converse));
|
2018-12-19 17:18:36 +01:00
|
|
|
|
|
2019-06-03 07:58:51 +02:00
|
|
|
|
const contact_jid = 'newguy@montague.lit';
|
2018-12-19 17:18:36 +01:00
|
|
|
|
let stanza = $pres({
|
2019-06-03 07:58:51 +02:00
|
|
|
|
'to': 'romeo@montague.lit/orchard',
|
|
|
|
|
'from': 'lounge@montague.lit/newguy'
|
2018-12-19 17:18:36 +01:00
|
|
|
|
})
|
|
|
|
|
.c('x', {xmlns: Strophe.NS.MUC_USER})
|
|
|
|
|
.c('item', {
|
|
|
|
|
'affiliation': 'none',
|
2019-06-03 07:58:51 +02:00
|
|
|
|
'jid': 'newguy@montague.lit/_converse.js-290929789',
|
2018-12-19 17:18:36 +01:00
|
|
|
|
'role': 'participant'
|
|
|
|
|
}).tree();
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
|
|
|
|
|
const toolbar = view.el.querySelector('.chat-toolbar');
|
|
|
|
|
const toggle = toolbar.querySelector('.toggle-omemo');
|
|
|
|
|
toggle.click();
|
|
|
|
|
expect(view.model.get('omemo_active')).toBe(true);
|
|
|
|
|
expect(view.model.get('omemo_supported')).toBe(true);
|
|
|
|
|
|
|
|
|
|
const textarea = view.el.querySelector('.chat-textarea');
|
|
|
|
|
textarea.value = 'This message will be encrypted';
|
2019-05-26 10:58:52 +02:00
|
|
|
|
view.onKeyDown({
|
2018-12-19 17:18:36 +01:00
|
|
|
|
target: textarea,
|
2019-08-05 11:14:49 +02:00
|
|
|
|
preventDefault: function preventDefault () {},
|
2018-12-19 17:18:36 +01:00
|
|
|
|
keyCode: 13 // Enter
|
|
|
|
|
});
|
2019-07-11 22:50:30 +02:00
|
|
|
|
let iq_stanza = await u.waitUntil(() => deviceListFetched(_converse, contact_jid));
|
2019-05-20 12:38:33 +02:00
|
|
|
|
expect(Strophe.serialize(iq_stanza)).toBe(
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`<iq from="romeo@montague.lit" id="${iq_stanza.getAttribute("id")}" to="${contact_jid}" type="get" xmlns="jabber:client">`+
|
2018-12-19 17:18:36 +01:00
|
|
|
|
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
|
|
|
|
`<items node="eu.siacs.conversations.axolotl.devicelist"/>`+
|
|
|
|
|
`</pubsub>`+
|
|
|
|
|
`</iq>`);
|
|
|
|
|
|
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': contact_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-12-19 17:18:36 +01:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {'xmlns': "http://jabber.org/protocol/pubsub"})
|
|
|
|
|
.c('items', {'node': "eu.siacs.conversations.axolotl.devicelist"})
|
|
|
|
|
.c('item', {'xmlns': "http://jabber.org/protocol/pubsub"}) // TODO: must have an id attribute
|
|
|
|
|
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
|
|
|
|
.c('device', {'id': '4e30f35051b7b8b42abe083742187228'}).up()
|
|
|
|
|
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => _converse.omemo_store);
|
2018-12-19 17:18:36 +01:00
|
|
|
|
expect(_converse.devicelists.length).toBe(2);
|
|
|
|
|
|
|
|
|
|
const devicelist = _converse.devicelists.get(contact_jid);
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => deviceListFetched(_converse, contact_jid));
|
2018-12-19 17:18:36 +01:00
|
|
|
|
expect(devicelist.devices.length).toBe(1);
|
|
|
|
|
expect(devicelist.devices.at(0).get('id')).toBe('4e30f35051b7b8b42abe083742187228');
|
|
|
|
|
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => bundleFetched(_converse, _converse.bare_jid, '482886413b977930064a5888b92134fe'));
|
2018-12-19 17:18:36 +01:00
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': _converse.bare_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-12-19 17:18:36 +01:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {
|
|
|
|
|
'xmlns': 'http://jabber.org/protocol/pubsub'
|
|
|
|
|
}).c('items', {'node': "eu.siacs.conversations.axolotl.bundles:482886413b977930064a5888b92134fe"})
|
|
|
|
|
.c('item')
|
|
|
|
|
.c('bundle', {'xmlns': 'eu.siacs.conversations.axolotl'})
|
|
|
|
|
.c('signedPreKeyPublic', {'signedPreKeyId': '4223'}).t(btoa('100000')).up()
|
|
|
|
|
.c('signedPreKeySignature').t(btoa('200000')).up()
|
|
|
|
|
.c('identityKey').t(btoa('300000')).up()
|
|
|
|
|
.c('prekeys')
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '1'}).t(btoa('1991')).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '2'}).t(btoa('1992')).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '3'}).t(btoa('1993'));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => bundleFetched(_converse, contact_jid, '4e30f35051b7b8b42abe083742187228'));
|
2018-12-19 17:18:36 +01:00
|
|
|
|
|
|
|
|
|
/* <iq xmlns="jabber:client" to="jc@opkode.com/converse.js-34183907" type="error" id="945c8ab3-b561-4d8a-92da-77c226bb1689:sendIQ" from="joris@konuro.net">
|
|
|
|
|
* <pubsub xmlns="http://jabber.org/protocol/pubsub">
|
|
|
|
|
* <items node="eu.siacs.conversations.axolotl.bundles:7580"/>
|
|
|
|
|
* </pubsub>
|
|
|
|
|
* <error code="401" type="auth">
|
|
|
|
|
* <presence-subscription-required xmlns="http://jabber.org/protocol/pubsub#errors"/>
|
|
|
|
|
* <not-authorized xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
|
|
|
|
|
* </error>
|
|
|
|
|
* </iq>
|
|
|
|
|
*/
|
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': contact_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-12-19 17:18:36 +01:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {'xmlns': 'http://jabber.org/protocol/pubsub'})
|
|
|
|
|
.c('items', {'node': "eu.siacs.conversations.axolotl.bundles:4e30f35051b7b8b42abe083742187228"}).up().up()
|
|
|
|
|
.c('error', {'code': '401', 'type': 'auth'})
|
|
|
|
|
.c('presence-subscription-required', {'xmlns':"http://jabber.org/protocol/pubsub#errors" }).up()
|
|
|
|
|
.c('not-authorized', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => document.querySelectorAll('.alert-danger').length, 2000);
|
2018-12-19 17:18:36 +01:00
|
|
|
|
const header = document.querySelector('.alert-danger .modal-title');
|
|
|
|
|
expect(header.textContent).toBe("Error");
|
|
|
|
|
expect(u.ancestor(header, '.modal-content').querySelector('.modal-body p').textContent.trim())
|
2019-06-03 07:58:51 +02:00
|
|
|
|
.toBe("Sorry, we're unable to send an encrypted message because newguy@montague.lit requires you "+
|
2018-12-19 17:18:36 +01:00
|
|
|
|
"to be subscribed to their presence in order to see their OMEMO information");
|
|
|
|
|
|
|
|
|
|
expect(view.model.get('omemo_supported')).toBe(false);
|
|
|
|
|
expect(view.el.querySelector('.chat-textarea').value).toBe('This message will be encrypted');
|
|
|
|
|
done();
|
|
|
|
|
}));
|
|
|
|
|
|
2018-08-27 14:25:34 +02:00
|
|
|
|
it("can receive a PreKeySignalMessage",
|
2019-02-12 14:21:45 +01:00
|
|
|
|
mock.initConverse(
|
2018-10-15 23:18:06 +02:00
|
|
|
|
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
|
|
|
|
async function (done, _converse) {
|
2018-08-27 14:25:34 +02:00
|
|
|
|
|
|
|
|
|
_converse.NUM_PREKEYS = 5; // Restrict to 5, otherwise the resulting stanza is too large to easily test
|
|
|
|
|
let view, sent_stanza;
|
|
|
|
|
test_utils.createContacts(_converse, 'current', 1);
|
2019-03-29 21:10:45 +01:00
|
|
|
|
_converse.api.trigger('rosterContactsFetched');
|
2019-06-03 07:58:51 +02:00
|
|
|
|
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
2018-08-27 14:25:34 +02:00
|
|
|
|
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => initializedOMEMO(_converse));
|
2018-10-15 23:18:06 +02:00
|
|
|
|
const obj = await _converse.ChatBox.prototype.encryptMessage('This is an encrypted message from the contact');
|
|
|
|
|
// XXX: Normally the key will be encrypted via libsignal.
|
|
|
|
|
// However, we're mocking libsignal in the tests, so we include
|
|
|
|
|
// it as plaintext in the message.
|
|
|
|
|
let stanza = $msg({
|
2018-08-27 14:25:34 +02:00
|
|
|
|
'from': contact_jid,
|
|
|
|
|
'to': _converse.connection.jid,
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'type': 'chat',
|
|
|
|
|
'id': 'qwerty'
|
|
|
|
|
}).c('body').t('This is a fallback message').up()
|
|
|
|
|
.c('encrypted', {'xmlns': Strophe.NS.OMEMO})
|
|
|
|
|
.c('header', {'sid': '555'})
|
|
|
|
|
.c('key', {
|
|
|
|
|
'prekey': 'true',
|
|
|
|
|
'rid': _converse.omemo_store.get('device_id')
|
|
|
|
|
}).t(u.arrayBufferToBase64(obj.key_and_tag)).up()
|
|
|
|
|
.c('iv').t(obj.iv)
|
|
|
|
|
.up().up()
|
|
|
|
|
.c('payload').t(obj.payload);
|
|
|
|
|
|
|
|
|
|
const generateMissingPreKeys = _converse.omemo_store.generateMissingPreKeys;
|
|
|
|
|
spyOn(_converse.omemo_store, 'generateMissingPreKeys').and.callFake(() => {
|
|
|
|
|
// Since it's difficult to override
|
|
|
|
|
// decryptPreKeyWhisperMessage, where a prekey will be
|
|
|
|
|
// removed from the store, we do it here, before the
|
|
|
|
|
// missing prekeys are generated.
|
|
|
|
|
_converse.omemo_store.removePreKey(1);
|
|
|
|
|
return generateMissingPreKeys.apply(_converse.omemo_store, arguments);
|
|
|
|
|
});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
let iq_stanza = await u.waitUntil(() => _converse.chatboxviews.get(contact_jid));
|
2018-10-15 23:18:06 +02:00
|
|
|
|
iq_stanza = await deviceListFetched(_converse, contact_jid);
|
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': contact_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.connection.jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {'xmlns': "http://jabber.org/protocol/pubsub"})
|
|
|
|
|
.c('items', {'node': "eu.siacs.conversations.axolotl.devicelist"})
|
|
|
|
|
.c('item', {'xmlns': "http://jabber.org/protocol/pubsub"}) // TODO: must have an id attribute
|
|
|
|
|
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
|
|
|
|
.c('device', {'id': '555'});
|
2018-08-27 14:25:34 +02:00
|
|
|
|
|
2018-10-15 23:18:06 +02:00
|
|
|
|
// XXX: the bundle gets published twice, we want to make sure
|
|
|
|
|
// that we wait for the 2nd, so we clear all the already sent
|
|
|
|
|
// stanzas.
|
|
|
|
|
_converse.connection.IQ_stanzas = [];
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => _converse.omemo_store);
|
2018-12-19 08:14:58 +01:00
|
|
|
|
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => bundleHasBeenPublished(_converse));
|
2019-05-20 12:38:33 +02:00
|
|
|
|
expect(Strophe.serialize(iq_stanza)).toBe(
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`<iq from="romeo@montague.lit" id="${iq_stanza.getAttribute("id")}" type="set" xmlns="jabber:client">`+
|
2018-10-15 23:18:06 +02:00
|
|
|
|
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
|
|
|
|
`<publish node="eu.siacs.conversations.axolotl.bundles:123456789">`+
|
|
|
|
|
`<item>`+
|
|
|
|
|
`<bundle xmlns="eu.siacs.conversations.axolotl">`+
|
|
|
|
|
`<signedPreKeyPublic signedPreKeyId="0">${btoa("1234")}</signedPreKeyPublic>`+
|
|
|
|
|
`<signedPreKeySignature>${btoa("11112222333344445555")}</signedPreKeySignature>`+
|
|
|
|
|
`<identityKey>${btoa("1234")}</identityKey>`+
|
|
|
|
|
`<prekeys>`+
|
|
|
|
|
`<preKeyPublic preKeyId="0">${btoa("1234")}</preKeyPublic>`+
|
|
|
|
|
`<preKeyPublic preKeyId="1">${btoa("1234")}</preKeyPublic>`+
|
|
|
|
|
`<preKeyPublic preKeyId="2">${btoa("1234")}</preKeyPublic>`+
|
|
|
|
|
`<preKeyPublic preKeyId="3">${btoa("1234")}</preKeyPublic>`+
|
|
|
|
|
`<preKeyPublic preKeyId="4">${btoa("1234")}</preKeyPublic>`+
|
|
|
|
|
`</prekeys>`+
|
|
|
|
|
`</bundle>`+
|
|
|
|
|
`</item>`+
|
|
|
|
|
`</publish>`+
|
2018-12-19 08:14:58 +01:00
|
|
|
|
`<publish-options>`+
|
|
|
|
|
`<x type="submit" xmlns="jabber:x:data">`+
|
|
|
|
|
`<field type="hidden" var="FORM_TYPE">`+
|
|
|
|
|
`<value>http://jabber.org/protocol/pubsub#publish-options</value>`+
|
|
|
|
|
`</field>`+
|
|
|
|
|
`<field var="pubsub#access_model">`+
|
|
|
|
|
`<value>open</value>`+
|
|
|
|
|
`</field>`+
|
|
|
|
|
`</x>`+
|
|
|
|
|
`</publish-options>`+
|
2018-10-15 23:18:06 +02:00
|
|
|
|
`</pubsub>`+
|
|
|
|
|
`</iq>`)
|
|
|
|
|
const own_device = _converse.devicelists.get(_converse.bare_jid).devices.get(_converse.omemo_store.get('device_id'));
|
|
|
|
|
expect(own_device.get('bundle').prekeys.length).toBe(5);
|
|
|
|
|
expect(_converse.omemo_store.generateMissingPreKeys).toHaveBeenCalled();
|
|
|
|
|
done();
|
2018-08-27 14:25:34 +02:00
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
2018-05-20 15:10:37 +02:00
|
|
|
|
it("updates device lists based on PEP messages",
|
2019-02-12 14:21:45 +01:00
|
|
|
|
mock.initConverse(
|
2018-10-10 20:12:29 +02:00
|
|
|
|
null, ['rosterGroupsFetched'], {'allow_non_roster_messaging': true},
|
2018-10-15 23:18:06 +02:00
|
|
|
|
async function (done, _converse) {
|
2018-05-20 13:41:16 +02:00
|
|
|
|
|
2018-12-19 08:14:58 +01:00
|
|
|
|
await test_utils.waitUntilDiscoConfirmed(
|
|
|
|
|
_converse, _converse.bare_jid,
|
|
|
|
|
[{'category': 'pubsub', 'type': 'pep'}],
|
|
|
|
|
['http://jabber.org/protocol/pubsub#publish-options']
|
|
|
|
|
);
|
|
|
|
|
|
2018-07-25 12:59:12 +02:00
|
|
|
|
test_utils.createContacts(_converse, 'current', 1);
|
2019-06-03 07:58:51 +02:00
|
|
|
|
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
2018-05-20 13:41:16 +02:00
|
|
|
|
|
2018-08-22 14:32:04 +02:00
|
|
|
|
// Wait until own devices are fetched
|
2019-07-11 22:50:30 +02:00
|
|
|
|
let iq_stanza = await u.waitUntil(() => deviceListFetched(_converse, _converse.bare_jid));
|
2019-05-20 12:38:33 +02:00
|
|
|
|
expect(Strophe.serialize(iq_stanza)).toBe(
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`<iq from="romeo@montague.lit" id="${iq_stanza.getAttribute("id")}" to="romeo@montague.lit" type="get" xmlns="jabber:client">`+
|
2018-10-15 23:18:06 +02:00
|
|
|
|
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
|
|
|
|
`<items node="eu.siacs.conversations.axolotl.devicelist"/>`+
|
|
|
|
|
`</pubsub>`+
|
|
|
|
|
`</iq>`);
|
|
|
|
|
|
|
|
|
|
let stanza = $iq({
|
|
|
|
|
'from': _converse.bare_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {'xmlns': "http://jabber.org/protocol/pubsub"})
|
|
|
|
|
.c('items', {'node': "eu.siacs.conversations.axolotl.devicelist"})
|
|
|
|
|
.c('item', {'xmlns': "http://jabber.org/protocol/pubsub"}) // TODO: must have an id attribute
|
|
|
|
|
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
|
|
|
|
.c('device', {'id': '555'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => _converse.omemo_store);
|
2018-10-15 23:18:06 +02:00
|
|
|
|
expect(_converse.chatboxes.length).toBe(1);
|
|
|
|
|
expect(_converse.devicelists.length).toBe(1);
|
|
|
|
|
const devicelist = _converse.devicelists.get(_converse.bare_jid);
|
|
|
|
|
expect(devicelist.devices.length).toBe(2);
|
|
|
|
|
expect(devicelist.devices.at(0).get('id')).toBe('555');
|
|
|
|
|
expect(devicelist.devices.at(1).get('id')).toBe('123456789');
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => ownDeviceHasBeenPublished(_converse));
|
2018-10-15 23:18:06 +02:00
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': _converse.bare_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => bundleHasBeenPublished(_converse));
|
2018-10-15 23:18:06 +02:00
|
|
|
|
|
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': _converse.bare_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
await _converse.api.waitUntil('OMEMOInitialized');
|
|
|
|
|
|
|
|
|
|
stanza = $msg({
|
|
|
|
|
'from': contact_jid,
|
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'headline',
|
|
|
|
|
'id': 'update_01',
|
|
|
|
|
}).c('event', {'xmlns': 'http://jabber.org/protocol/pubsub#event'})
|
|
|
|
|
.c('items', {'node': 'eu.siacs.conversations.axolotl.devicelist'})
|
|
|
|
|
.c('item')
|
|
|
|
|
.c('list', {'xmlns': 'eu.siacs.conversations.axolotl'})
|
|
|
|
|
.c('device', {'id': '1234'})
|
|
|
|
|
.c('device', {'id': '4223'})
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
|
|
|
|
|
expect(_converse.devicelists.length).toBe(2);
|
|
|
|
|
let devices = _converse.devicelists.get(contact_jid).devices;
|
|
|
|
|
expect(devices.length).toBe(2);
|
|
|
|
|
expect(_.map(devices.models, 'attributes.id').sort().join()).toBe('1234,4223');
|
|
|
|
|
|
|
|
|
|
stanza = $msg({
|
|
|
|
|
'from': contact_jid,
|
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'headline',
|
|
|
|
|
'id': 'update_02',
|
|
|
|
|
}).c('event', {'xmlns': 'http://jabber.org/protocol/pubsub#event'})
|
|
|
|
|
.c('items', {'node': 'eu.siacs.conversations.axolotl.devicelist'})
|
|
|
|
|
.c('item')
|
|
|
|
|
.c('list', {'xmlns': 'eu.siacs.conversations.axolotl'})
|
|
|
|
|
.c('device', {'id': '4223'})
|
|
|
|
|
.c('device', {'id': '4224'})
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
|
|
|
|
|
expect(_converse.devicelists.length).toBe(2);
|
2019-03-30 18:01:36 +01:00
|
|
|
|
expect(devices.length).toBe(3);
|
|
|
|
|
expect(_.map(devices.models, 'attributes.id').sort().join()).toBe('1234,4223,4224');
|
|
|
|
|
expect(devices.get('1234').get('active')).toBe(false);
|
|
|
|
|
expect(devices.get('4223').get('active')).toBe(true);
|
|
|
|
|
expect(devices.get('4224').get('active')).toBe(true);
|
2018-10-15 23:18:06 +02:00
|
|
|
|
|
|
|
|
|
// Check that own devicelist gets updated
|
|
|
|
|
stanza = $msg({
|
|
|
|
|
'from': _converse.bare_jid,
|
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'headline',
|
|
|
|
|
'id': 'update_03',
|
|
|
|
|
}).c('event', {'xmlns': 'http://jabber.org/protocol/pubsub#event'})
|
|
|
|
|
.c('items', {'node': 'eu.siacs.conversations.axolotl.devicelist'})
|
|
|
|
|
.c('item')
|
|
|
|
|
.c('list', {'xmlns': 'eu.siacs.conversations.axolotl'})
|
|
|
|
|
.c('device', {'id': '123456789'})
|
|
|
|
|
.c('device', {'id': '555'})
|
|
|
|
|
.c('device', {'id': '777'})
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
|
|
|
|
|
expect(_converse.devicelists.length).toBe(2);
|
|
|
|
|
devices = _converse.devicelists.get(_converse.bare_jid).devices;
|
|
|
|
|
expect(devices.length).toBe(3);
|
|
|
|
|
expect(_.map(devices.models, 'attributes.id').sort().join()).toBe('123456789,555,777');
|
2019-03-30 18:01:36 +01:00
|
|
|
|
expect(devices.get('123456789').get('active')).toBe(true);
|
|
|
|
|
expect(devices.get('555').get('active')).toBe(true);
|
|
|
|
|
expect(devices.get('777').get('active')).toBe(true);
|
2018-10-15 23:18:06 +02:00
|
|
|
|
|
|
|
|
|
_converse.connection.IQ_stanzas = [];
|
|
|
|
|
|
|
|
|
|
// Check that own device gets re-added
|
|
|
|
|
stanza = $msg({
|
|
|
|
|
'from': _converse.bare_jid,
|
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'headline',
|
|
|
|
|
'id': 'update_04',
|
|
|
|
|
}).c('event', {'xmlns': 'http://jabber.org/protocol/pubsub#event'})
|
|
|
|
|
.c('items', {'node': 'eu.siacs.conversations.axolotl.devicelist'})
|
|
|
|
|
.c('item')
|
|
|
|
|
.c('list', {'xmlns': 'eu.siacs.conversations.axolotl'})
|
|
|
|
|
.c('device', {'id': '444'})
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => ownDeviceHasBeenPublished(_converse));
|
2018-10-15 23:18:06 +02:00
|
|
|
|
// Check that our own device is added again, but that removed
|
|
|
|
|
// devices are not added.
|
2019-05-20 12:38:33 +02:00
|
|
|
|
expect(Strophe.serialize(iq_stanza)).toBe(
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`<iq from="romeo@montague.lit" id="${iq_stanza.getAttribute(`id`)}" type="set" xmlns="jabber:client">`+
|
2018-10-15 23:18:06 +02:00
|
|
|
|
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
|
|
|
|
`<publish node="eu.siacs.conversations.axolotl.devicelist">`+
|
|
|
|
|
`<item>`+
|
|
|
|
|
`<list xmlns="eu.siacs.conversations.axolotl">`+
|
|
|
|
|
`<device id="123456789"/>`+
|
|
|
|
|
`<device id="444"/>`+
|
|
|
|
|
`</list>`+
|
|
|
|
|
`</item>`+
|
|
|
|
|
`</publish>`+
|
2018-12-19 08:14:58 +01:00
|
|
|
|
`<publish-options>`+
|
|
|
|
|
`<x type="submit" xmlns="jabber:x:data">`+
|
|
|
|
|
`<field type="hidden" var="FORM_TYPE">`+
|
|
|
|
|
`<value>http://jabber.org/protocol/pubsub#publish-options</value>`+
|
|
|
|
|
`</field>`+
|
|
|
|
|
`<field var="pubsub#access_model">`+
|
|
|
|
|
`<value>open</value>`+
|
|
|
|
|
`</field>`+
|
|
|
|
|
`</x>`+
|
|
|
|
|
`</publish-options>`+
|
2018-10-15 23:18:06 +02:00
|
|
|
|
`</pubsub>`+
|
|
|
|
|
`</iq>`);
|
|
|
|
|
expect(_converse.devicelists.length).toBe(2);
|
|
|
|
|
devices = _converse.devicelists.get(_converse.bare_jid).devices;
|
|
|
|
|
// The device id for this device (123456789) was also generated and added to the list,
|
|
|
|
|
// which is why we have 2 devices now.
|
2019-03-30 18:01:36 +01:00
|
|
|
|
expect(devices.length).toBe(4);
|
|
|
|
|
expect(_.map(devices.models, 'attributes.id').sort().join()).toBe('123456789,444,555,777');
|
|
|
|
|
expect(devices.get('123456789').get('active')).toBe(true);
|
|
|
|
|
expect(devices.get('444').get('active')).toBe(true);
|
|
|
|
|
expect(devices.get('555').get('active')).toBe(false);
|
|
|
|
|
expect(devices.get('777').get('active')).toBe(false);
|
2018-10-15 23:18:06 +02:00
|
|
|
|
done();
|
2018-05-20 13:41:16 +02:00
|
|
|
|
}));
|
|
|
|
|
|
2018-08-27 14:25:34 +02:00
|
|
|
|
|
2018-05-20 15:10:37 +02:00
|
|
|
|
it("updates device bundles based on PEP messages",
|
2019-02-12 14:21:45 +01:00
|
|
|
|
mock.initConverse(
|
2018-05-20 15:10:37 +02:00
|
|
|
|
null, ['rosterGroupsFetched'], {},
|
2018-10-15 23:18:06 +02:00
|
|
|
|
async function (done, _converse) {
|
2018-05-20 15:10:37 +02:00
|
|
|
|
|
2018-12-19 08:14:58 +01:00
|
|
|
|
await test_utils.waitUntilDiscoConfirmed(
|
|
|
|
|
_converse, _converse.bare_jid,
|
|
|
|
|
[{'category': 'pubsub', 'type': 'pep'}],
|
|
|
|
|
['http://jabber.org/protocol/pubsub#publish-options']
|
|
|
|
|
);
|
|
|
|
|
|
2018-05-20 15:10:37 +02:00
|
|
|
|
test_utils.createContacts(_converse, 'current');
|
2019-06-03 07:58:51 +02:00
|
|
|
|
const contact_jid = mock.cur_names[3].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
2019-07-11 22:50:30 +02:00
|
|
|
|
let iq_stanza = await u.waitUntil(() => deviceListFetched(_converse, _converse.bare_jid));
|
2019-05-20 12:38:33 +02:00
|
|
|
|
expect(Strophe.serialize(iq_stanza)).toBe(
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`<iq from="romeo@montague.lit" id="${iq_stanza.getAttribute("id")}" to="romeo@montague.lit" type="get" xmlns="jabber:client">`+
|
2018-10-15 23:18:06 +02:00
|
|
|
|
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
|
|
|
|
`<items node="eu.siacs.conversations.axolotl.devicelist"/>`+
|
|
|
|
|
`</pubsub>`+
|
|
|
|
|
`</iq>`);
|
|
|
|
|
|
|
|
|
|
let stanza = $iq({
|
|
|
|
|
'from': contact_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {'xmlns': "http://jabber.org/protocol/pubsub"})
|
|
|
|
|
.c('items', {'node': "eu.siacs.conversations.axolotl.devicelist"})
|
|
|
|
|
.c('item', {'xmlns': "http://jabber.org/protocol/pubsub"}) // TODO: must have an id attribute
|
|
|
|
|
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
|
|
|
|
.c('device', {'id': '555'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await await u.waitUntil(() => _converse.omemo_store);
|
2018-10-15 23:18:06 +02:00
|
|
|
|
expect(_converse.devicelists.length).toBe(1);
|
|
|
|
|
let devicelist = _converse.devicelists.get(_converse.bare_jid);
|
|
|
|
|
expect(devicelist.devices.length).toBe(2);
|
|
|
|
|
expect(devicelist.devices.at(0).get('id')).toBe('555');
|
|
|
|
|
expect(devicelist.devices.at(1).get('id')).toBe('123456789');
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => ownDeviceHasBeenPublished(_converse));
|
2018-10-15 23:18:06 +02:00
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': _converse.bare_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => bundleHasBeenPublished(_converse));
|
2018-10-15 23:18:06 +02:00
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': _converse.bare_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
await _converse.api.waitUntil('OMEMOInitialized');
|
|
|
|
|
stanza = $msg({
|
|
|
|
|
'from': contact_jid,
|
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'headline',
|
|
|
|
|
'id': 'update_01',
|
|
|
|
|
}).c('event', {'xmlns': 'http://jabber.org/protocol/pubsub#event'})
|
|
|
|
|
.c('items', {'node': 'eu.siacs.conversations.axolotl.bundles:555'})
|
|
|
|
|
.c('item')
|
|
|
|
|
.c('bundle', {'xmlns': 'eu.siacs.conversations.axolotl'})
|
|
|
|
|
.c('signedPreKeyPublic', {'signedPreKeyId': '4223'}).t('1111').up()
|
|
|
|
|
.c('signedPreKeySignature').t('2222').up()
|
|
|
|
|
.c('identityKey').t('3333').up()
|
|
|
|
|
.c('prekeys')
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '1001'}).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '1002'}).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '1003'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2018-05-20 15:10:37 +02:00
|
|
|
|
|
2018-10-15 23:18:06 +02:00
|
|
|
|
expect(_converse.devicelists.length).toBe(2);
|
|
|
|
|
devicelist = _converse.devicelists.get(contact_jid);
|
|
|
|
|
expect(devicelist.devices.length).toBe(1);
|
|
|
|
|
let device = devicelist.devices.at(0);
|
|
|
|
|
expect(device.get('bundle').identity_key).toBe('3333');
|
|
|
|
|
expect(device.get('bundle').signed_prekey.public_key).toBe('1111');
|
|
|
|
|
expect(device.get('bundle').signed_prekey.id).toBe(4223);
|
|
|
|
|
expect(device.get('bundle').signed_prekey.signature).toBe('2222');
|
|
|
|
|
expect(device.get('bundle').prekeys.length).toBe(3);
|
|
|
|
|
expect(device.get('bundle').prekeys[0].id).toBe(1001);
|
|
|
|
|
expect(device.get('bundle').prekeys[1].id).toBe(1002);
|
|
|
|
|
expect(device.get('bundle').prekeys[2].id).toBe(1003);
|
|
|
|
|
|
|
|
|
|
stanza = $msg({
|
|
|
|
|
'from': contact_jid,
|
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'headline',
|
|
|
|
|
'id': 'update_02',
|
|
|
|
|
}).c('event', {'xmlns': 'http://jabber.org/protocol/pubsub#event'})
|
|
|
|
|
.c('items', {'node': 'eu.siacs.conversations.axolotl.bundles:555'})
|
|
|
|
|
.c('item')
|
|
|
|
|
.c('bundle', {'xmlns': 'eu.siacs.conversations.axolotl'})
|
|
|
|
|
.c('signedPreKeyPublic', {'signedPreKeyId': '4223'}).t('5555').up()
|
|
|
|
|
.c('signedPreKeySignature').t('6666').up()
|
|
|
|
|
.c('identityKey').t('7777').up()
|
|
|
|
|
.c('prekeys')
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '2001'}).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '2002'}).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '2003'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2018-05-20 15:10:37 +02:00
|
|
|
|
|
2018-10-15 23:18:06 +02:00
|
|
|
|
expect(_converse.devicelists.length).toBe(2);
|
|
|
|
|
devicelist = _converse.devicelists.get(contact_jid);
|
|
|
|
|
expect(devicelist.devices.length).toBe(1);
|
|
|
|
|
device = devicelist.devices.at(0);
|
|
|
|
|
expect(device.get('bundle').identity_key).toBe('7777');
|
|
|
|
|
expect(device.get('bundle').signed_prekey.public_key).toBe('5555');
|
|
|
|
|
expect(device.get('bundle').signed_prekey.id).toBe(4223);
|
|
|
|
|
expect(device.get('bundle').signed_prekey.signature).toBe('6666');
|
|
|
|
|
expect(device.get('bundle').prekeys.length).toBe(3);
|
|
|
|
|
expect(device.get('bundle').prekeys[0].id).toBe(2001);
|
|
|
|
|
expect(device.get('bundle').prekeys[1].id).toBe(2002);
|
|
|
|
|
expect(device.get('bundle').prekeys[2].id).toBe(2003);
|
|
|
|
|
|
|
|
|
|
stanza = $msg({
|
|
|
|
|
'from': _converse.bare_jid,
|
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'headline',
|
|
|
|
|
'id': 'update_03',
|
|
|
|
|
}).c('event', {'xmlns': 'http://jabber.org/protocol/pubsub#event'})
|
|
|
|
|
.c('items', {'node': 'eu.siacs.conversations.axolotl.bundles:123456789'})
|
|
|
|
|
.c('item')
|
|
|
|
|
.c('bundle', {'xmlns': 'eu.siacs.conversations.axolotl'})
|
|
|
|
|
.c('signedPreKeyPublic', {'signedPreKeyId': '9999'}).t('8888').up()
|
|
|
|
|
.c('signedPreKeySignature').t('3333').up()
|
|
|
|
|
.c('identityKey').t('1111').up()
|
|
|
|
|
.c('prekeys')
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '3001'}).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '3002'}).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '3003'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
|
|
|
|
|
expect(_converse.devicelists.length).toBe(2);
|
|
|
|
|
devicelist = _converse.devicelists.get(_converse.bare_jid);
|
|
|
|
|
expect(devicelist.devices.length).toBe(2);
|
|
|
|
|
expect(devicelist.devices.at(0).get('id')).toBe('555');
|
|
|
|
|
expect(devicelist.devices.at(1).get('id')).toBe('123456789');
|
|
|
|
|
device = devicelist.devices.at(1);
|
|
|
|
|
expect(device.get('bundle').identity_key).toBe('1111');
|
|
|
|
|
expect(device.get('bundle').signed_prekey.public_key).toBe('8888');
|
|
|
|
|
expect(device.get('bundle').signed_prekey.id).toBe(9999);
|
|
|
|
|
expect(device.get('bundle').signed_prekey.signature).toBe('3333');
|
|
|
|
|
expect(device.get('bundle').prekeys.length).toBe(3);
|
|
|
|
|
expect(device.get('bundle').prekeys[0].id).toBe(3001);
|
|
|
|
|
expect(device.get('bundle').prekeys[1].id).toBe(3002);
|
|
|
|
|
expect(device.get('bundle').prekeys[2].id).toBe(3003);
|
|
|
|
|
done();
|
2018-05-20 15:10:37 +02:00
|
|
|
|
}));
|
|
|
|
|
|
2018-07-21 21:51:50 +02:00
|
|
|
|
it("publishes a bundle with which an encrypted session can be created",
|
2019-02-12 14:21:45 +01:00
|
|
|
|
mock.initConverse(
|
2018-10-15 23:18:06 +02:00
|
|
|
|
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
|
|
|
|
async function (done, _converse) {
|
2018-07-21 21:51:50 +02:00
|
|
|
|
|
2018-12-19 08:14:58 +01:00
|
|
|
|
await test_utils.waitUntilDiscoConfirmed(
|
|
|
|
|
_converse, _converse.bare_jid,
|
|
|
|
|
[{'category': 'pubsub', 'type': 'pep'}],
|
|
|
|
|
['http://jabber.org/protocol/pubsub#publish-options']
|
|
|
|
|
);
|
|
|
|
|
|
2018-07-22 10:33:57 +02:00
|
|
|
|
_converse.NUM_PREKEYS = 2; // Restrict to 2, otherwise the resulting stanza is too large to easily test
|
|
|
|
|
|
2018-07-21 21:51:50 +02:00
|
|
|
|
test_utils.createContacts(_converse, 'current', 1);
|
2019-03-29 21:10:45 +01:00
|
|
|
|
_converse.api.trigger('rosterContactsFetched');
|
2019-06-03 07:58:51 +02:00
|
|
|
|
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
2019-07-11 22:50:30 +02:00
|
|
|
|
let iq_stanza = await u.waitUntil(() => deviceListFetched(_converse, _converse.bare_jid));
|
2018-10-15 23:18:06 +02:00
|
|
|
|
let stanza = $iq({
|
|
|
|
|
'from': contact_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {'xmlns': "http://jabber.org/protocol/pubsub"})
|
|
|
|
|
.c('items', {'node': "eu.siacs.conversations.axolotl.devicelist"})
|
|
|
|
|
.c('item', {'xmlns': "http://jabber.org/protocol/pubsub"}) // TODO: must have an id attribute
|
|
|
|
|
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
|
|
|
|
.c('device', {'id': '482886413b977930064a5888b92134fe'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
expect(_converse.devicelists.length).toBe(1);
|
|
|
|
|
await test_utils.openChatBoxFor(_converse, contact_jid);
|
|
|
|
|
iq_stanza = await ownDeviceHasBeenPublished(_converse);
|
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': _converse.bare_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2018-07-21 21:51:50 +02:00
|
|
|
|
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => bundleHasBeenPublished(_converse));
|
2019-05-20 12:38:33 +02:00
|
|
|
|
expect(Strophe.serialize(iq_stanza)).toBe(
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`<iq from="romeo@montague.lit" id="${iq_stanza.getAttribute("id")}" type="set" xmlns="jabber:client">`+
|
2018-10-15 23:18:06 +02:00
|
|
|
|
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
|
|
|
|
`<publish node="eu.siacs.conversations.axolotl.bundles:123456789">`+
|
|
|
|
|
`<item>`+
|
|
|
|
|
`<bundle xmlns="eu.siacs.conversations.axolotl">`+
|
|
|
|
|
`<signedPreKeyPublic signedPreKeyId="0">${btoa("1234")}</signedPreKeyPublic>`+
|
|
|
|
|
`<signedPreKeySignature>${btoa("11112222333344445555")}</signedPreKeySignature>`+
|
|
|
|
|
`<identityKey>${btoa("1234")}</identityKey>`+
|
|
|
|
|
`<prekeys>`+
|
|
|
|
|
`<preKeyPublic preKeyId="0">${btoa("1234")}</preKeyPublic>`+
|
|
|
|
|
`<preKeyPublic preKeyId="1">${btoa("1234")}</preKeyPublic>`+
|
|
|
|
|
`</prekeys>`+
|
|
|
|
|
`</bundle>`+
|
|
|
|
|
`</item>`+
|
|
|
|
|
`</publish>`+
|
2018-12-19 08:14:58 +01:00
|
|
|
|
`<publish-options>`+
|
|
|
|
|
`<x type="submit" xmlns="jabber:x:data">`+
|
|
|
|
|
`<field type="hidden" var="FORM_TYPE">`+
|
|
|
|
|
`<value>http://jabber.org/protocol/pubsub#publish-options</value>`+
|
|
|
|
|
`</field>`+
|
|
|
|
|
`<field var="pubsub#access_model">`+
|
|
|
|
|
`<value>open</value>`+
|
|
|
|
|
`</field>`+
|
|
|
|
|
`</x>`+
|
|
|
|
|
`</publish-options>`+
|
2018-10-15 23:18:06 +02:00
|
|
|
|
`</pubsub>`+
|
|
|
|
|
`</iq>`)
|
|
|
|
|
|
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': _converse.bare_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
await _converse.api.waitUntil('OMEMOInitialized');
|
|
|
|
|
done();
|
2018-07-21 21:51:50 +02:00
|
|
|
|
}));
|
|
|
|
|
|
2018-08-26 19:33:34 +02:00
|
|
|
|
|
2018-05-12 19:37:44 +02:00
|
|
|
|
it("adds a toolbar button for starting an encrypted chat session",
|
2019-02-12 14:21:45 +01:00
|
|
|
|
mock.initConverse(
|
2018-08-04 08:39:14 +02:00
|
|
|
|
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
2018-10-15 23:18:06 +02:00
|
|
|
|
async function (done, _converse) {
|
2018-05-12 19:37:44 +02:00
|
|
|
|
|
2018-12-19 08:14:58 +01:00
|
|
|
|
await test_utils.waitUntilDiscoConfirmed(
|
|
|
|
|
_converse, _converse.bare_jid,
|
|
|
|
|
[{'category': 'pubsub', 'type': 'pep'}],
|
|
|
|
|
['http://jabber.org/protocol/pubsub#publish-options']
|
|
|
|
|
);
|
|
|
|
|
|
2018-07-21 21:51:50 +02:00
|
|
|
|
test_utils.createContacts(_converse, 'current', 1);
|
2019-03-29 21:10:45 +01:00
|
|
|
|
_converse.api.trigger('rosterContactsFetched');
|
2019-06-03 07:58:51 +02:00
|
|
|
|
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
2018-05-12 19:37:44 +02:00
|
|
|
|
|
2019-07-11 22:50:30 +02:00
|
|
|
|
let iq_stanza = await u.waitUntil(() => deviceListFetched(_converse, _converse.bare_jid));
|
2019-05-20 12:38:33 +02:00
|
|
|
|
expect(Strophe.serialize(iq_stanza)).toBe(
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`<iq from="romeo@montague.lit" id="${iq_stanza.getAttribute("id")}" to="romeo@montague.lit" type="get" xmlns="jabber:client">`+
|
2018-10-15 23:18:06 +02:00
|
|
|
|
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
|
|
|
|
`<items node="eu.siacs.conversations.axolotl.devicelist"/>`+
|
2018-09-25 14:05:56 +02:00
|
|
|
|
`</pubsub>`+
|
2018-10-15 23:18:06 +02:00
|
|
|
|
`</iq>`);
|
2018-05-13 16:04:52 +02:00
|
|
|
|
|
2018-10-15 23:18:06 +02:00
|
|
|
|
let stanza = $iq({
|
|
|
|
|
'from': _converse.bare_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {'xmlns': "http://jabber.org/protocol/pubsub"})
|
|
|
|
|
.c('items', {'node': "eu.siacs.conversations.axolotl.devicelist"})
|
|
|
|
|
.c('item', {'xmlns': "http://jabber.org/protocol/pubsub"}) // TODO: must have an id attribute
|
|
|
|
|
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
|
|
|
|
.c('device', {'id': '482886413b977930064a5888b92134fe'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => _converse.omemo_store);
|
2018-10-15 23:18:06 +02:00
|
|
|
|
expect(_converse.devicelists.length).toBe(1);
|
|
|
|
|
let devicelist = _converse.devicelists.get(_converse.bare_jid);
|
|
|
|
|
expect(devicelist.devices.length).toBe(2);
|
|
|
|
|
expect(devicelist.devices.at(0).get('id')).toBe('482886413b977930064a5888b92134fe');
|
|
|
|
|
expect(devicelist.devices.at(1).get('id')).toBe('123456789');
|
|
|
|
|
// Check that own device was published
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => ownDeviceHasBeenPublished(_converse));
|
2019-05-20 12:38:33 +02:00
|
|
|
|
expect(Strophe.serialize(iq_stanza)).toBe(
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`<iq from="romeo@montague.lit" id="${iq_stanza.getAttribute(`id`)}" type="set" xmlns="jabber:client">`+
|
2018-10-15 23:18:06 +02:00
|
|
|
|
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
|
|
|
|
`<publish node="eu.siacs.conversations.axolotl.devicelist">`+
|
|
|
|
|
`<item>`+
|
|
|
|
|
`<list xmlns="eu.siacs.conversations.axolotl">`+
|
|
|
|
|
`<device id="482886413b977930064a5888b92134fe"/>`+
|
|
|
|
|
`<device id="123456789"/>`+
|
|
|
|
|
`</list>`+
|
|
|
|
|
`</item>`+
|
|
|
|
|
`</publish>`+
|
2018-12-19 08:14:58 +01:00
|
|
|
|
`<publish-options>`+
|
|
|
|
|
`<x type="submit" xmlns="jabber:x:data">`+
|
|
|
|
|
`<field type="hidden" var="FORM_TYPE">`+
|
|
|
|
|
`<value>http://jabber.org/protocol/pubsub#publish-options</value>`+
|
|
|
|
|
`</field>`+
|
|
|
|
|
`<field var="pubsub#access_model">`+
|
|
|
|
|
`<value>open</value>`+
|
|
|
|
|
`</field>`+
|
|
|
|
|
`</x>`+
|
|
|
|
|
`</publish-options>`+
|
|
|
|
|
`</pubsub>`+
|
2018-10-15 23:18:06 +02:00
|
|
|
|
`</iq>`);
|
|
|
|
|
|
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': _converse.bare_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
|
2019-07-11 22:50:30 +02:00
|
|
|
|
const iq_el = await u.waitUntil(() => bundleHasBeenPublished(_converse));
|
2018-10-15 23:18:06 +02:00
|
|
|
|
expect(iq_el.getAttributeNames().sort().join()).toBe(["from", "type", "xmlns", "id"].sort().join());
|
|
|
|
|
expect(iq_el.querySelector('prekeys').childNodes.length).toBe(100);
|
|
|
|
|
|
|
|
|
|
const signed_prekeys = iq_el.querySelectorAll('signedPreKeyPublic');
|
|
|
|
|
expect(signed_prekeys.length).toBe(1);
|
|
|
|
|
const signed_prekey = signed_prekeys[0];
|
|
|
|
|
expect(signed_prekey.getAttribute('signedPreKeyId')).toBe('0')
|
|
|
|
|
expect(iq_el.querySelectorAll('signedPreKeySignature').length).toBe(1);
|
|
|
|
|
expect(iq_el.querySelectorAll('identityKey').length).toBe(1);
|
|
|
|
|
|
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': _converse.bare_jid,
|
|
|
|
|
'id': iq_el.getAttribute('id'),
|
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
await _converse.api.waitUntil('OMEMOInitialized', 1000);
|
|
|
|
|
await test_utils.openChatBoxFor(_converse, contact_jid);
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => deviceListFetched(_converse, contact_jid));
|
2019-05-20 12:38:33 +02:00
|
|
|
|
expect(Strophe.serialize(iq_stanza)).toBe(
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`<iq from="romeo@montague.lit" id="${iq_stanza.getAttribute("id")}" to="${contact_jid}" type="get" xmlns="jabber:client">`+
|
2018-10-15 23:18:06 +02:00
|
|
|
|
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
|
|
|
|
`<items node="eu.siacs.conversations.axolotl.devicelist"/>`+
|
|
|
|
|
`</pubsub>`+
|
|
|
|
|
`</iq>`);
|
|
|
|
|
|
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': contact_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {'xmlns': "http://jabber.org/protocol/pubsub"})
|
|
|
|
|
.c('items', {'node': "eu.siacs.conversations.axolotl.devicelist"})
|
|
|
|
|
.c('item', {'xmlns': "http://jabber.org/protocol/pubsub"}) // TODO: must have an id attribute
|
|
|
|
|
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
|
|
|
|
.c('device', {'id': '368866411b877c30064a5f62b917cffe'}).up()
|
|
|
|
|
.c('device', {'id': '3300659945416e274474e469a1f0154c'}).up()
|
|
|
|
|
.c('device', {'id': '4e30f35051b7b8b42abe083742187228'}).up()
|
|
|
|
|
.c('device', {'id': 'ae890ac52d0df67ed7cfdf51b644e901'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
devicelist = _converse.devicelists.get(contact_jid);
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => devicelist.devices.length);
|
2018-10-15 23:18:06 +02:00
|
|
|
|
expect(_converse.devicelists.length).toBe(2);
|
|
|
|
|
devicelist = _converse.devicelists.get(contact_jid);
|
|
|
|
|
expect(devicelist.devices.length).toBe(4);
|
|
|
|
|
expect(devicelist.devices.at(0).get('id')).toBe('368866411b877c30064a5f62b917cffe');
|
|
|
|
|
expect(devicelist.devices.at(1).get('id')).toBe('3300659945416e274474e469a1f0154c');
|
|
|
|
|
expect(devicelist.devices.at(2).get('id')).toBe('4e30f35051b7b8b42abe083742187228');
|
|
|
|
|
expect(devicelist.devices.at(3).get('id')).toBe('ae890ac52d0df67ed7cfdf51b644e901');
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => _converse.chatboxviews.get(contact_jid).el.querySelector('.chat-toolbar'));
|
2018-10-15 23:18:06 +02:00
|
|
|
|
const view = _converse.chatboxviews.get(contact_jid);
|
|
|
|
|
const toolbar = view.el.querySelector('.chat-toolbar');
|
|
|
|
|
expect(view.model.get('omemo_active')).toBe(undefined);
|
|
|
|
|
let toggle = toolbar.querySelector('.toggle-omemo');
|
2019-08-05 01:39:57 +02:00
|
|
|
|
expect(toggle === null).toBe(false);
|
2018-10-15 23:18:06 +02:00
|
|
|
|
expect(u.hasClass('fa-unlock', toggle)).toBe(true);
|
|
|
|
|
expect(u.hasClass('fa-lock', toggle)).toBe(false);
|
|
|
|
|
|
|
|
|
|
spyOn(view, 'toggleOMEMO').and.callThrough();
|
|
|
|
|
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
|
|
|
|
|
toolbar.querySelector('.toggle-omemo').click();
|
|
|
|
|
expect(view.toggleOMEMO).toHaveBeenCalled();
|
|
|
|
|
expect(view.model.get('omemo_active')).toBe(true);
|
|
|
|
|
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => u.hasClass('fa-lock', toolbar.querySelector('.toggle-omemo')));
|
2018-10-15 23:18:06 +02:00
|
|
|
|
toggle = toolbar.querySelector('.toggle-omemo');
|
|
|
|
|
expect(u.hasClass('fa-unlock', toggle)).toBe(false);
|
|
|
|
|
expect(u.hasClass('fa-lock', toggle)).toBe(true);
|
|
|
|
|
|
|
|
|
|
const textarea = view.el.querySelector('.chat-textarea');
|
|
|
|
|
textarea.value = 'This message will be sent encrypted';
|
2019-05-26 10:58:52 +02:00
|
|
|
|
view.onKeyDown({
|
2018-10-15 23:18:06 +02:00
|
|
|
|
target: textarea,
|
2019-08-05 11:14:49 +02:00
|
|
|
|
preventDefault: function preventDefault () {},
|
2018-10-15 23:18:06 +02:00
|
|
|
|
keyCode: 13
|
|
|
|
|
});
|
2018-12-13 15:36:37 +01:00
|
|
|
|
|
|
|
|
|
view.model.save({'omemo_supported': false});
|
|
|
|
|
toggle = toolbar.querySelector('.toggle-omemo');
|
|
|
|
|
expect(u.hasClass('fa-lock', toggle)).toBe(false);
|
|
|
|
|
expect(u.hasClass('fa-unlock', toggle)).toBe(true);
|
|
|
|
|
expect(u.hasClass('disabled', toggle)).toBe(true);
|
|
|
|
|
|
|
|
|
|
view.model.save({'omemo_supported': true});
|
|
|
|
|
toggle = toolbar.querySelector('.toggle-omemo');
|
|
|
|
|
expect(u.hasClass('fa-lock', toggle)).toBe(false);
|
|
|
|
|
expect(u.hasClass('fa-unlock', toggle)).toBe(true);
|
|
|
|
|
expect(u.hasClass('disabled', toggle)).toBe(false);
|
2018-10-15 23:18:06 +02:00
|
|
|
|
done();
|
2018-05-12 19:37:44 +02:00
|
|
|
|
}));
|
2018-07-22 16:12:36 +02:00
|
|
|
|
|
2018-12-13 09:48:43 +01:00
|
|
|
|
it("adds a toolbar button for starting an encrypted groupchat session",
|
2019-02-12 14:21:45 +01:00
|
|
|
|
mock.initConverse(
|
2018-12-13 09:48:43 +01:00
|
|
|
|
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {'view_mode': 'fullscreen'},
|
|
|
|
|
async function (done, _converse) {
|
|
|
|
|
|
2018-12-19 08:14:58 +01:00
|
|
|
|
await test_utils.waitUntilDiscoConfirmed(
|
|
|
|
|
_converse, _converse.bare_jid,
|
|
|
|
|
[{'category': 'pubsub', 'type': 'pep'}],
|
|
|
|
|
['http://jabber.org/protocol/pubsub#publish-options']
|
|
|
|
|
);
|
|
|
|
|
|
2019-07-03 14:18:46 +02:00
|
|
|
|
// MEMO encryption works only in members-only conferences that are non-anonymous.
|
2018-12-13 09:48:43 +01:00
|
|
|
|
const features = [
|
|
|
|
|
'http://jabber.org/protocol/muc',
|
|
|
|
|
'jabber:iq:register',
|
|
|
|
|
'muc_passwordprotected',
|
|
|
|
|
'muc_hidden',
|
|
|
|
|
'muc_temporary',
|
|
|
|
|
'muc_membersonly',
|
|
|
|
|
'muc_unmoderated',
|
|
|
|
|
'muc_nonanonymous'
|
|
|
|
|
];
|
2019-07-03 14:18:46 +02:00
|
|
|
|
await test_utils.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo', features);
|
2019-06-03 07:58:51 +02:00
|
|
|
|
const view = _converse.chatboxviews.get('lounge@montague.lit');
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => initializedOMEMO(_converse));
|
2018-12-13 09:48:43 +01:00
|
|
|
|
|
|
|
|
|
const toolbar = view.el.querySelector('.chat-toolbar');
|
|
|
|
|
let toggle = toolbar.querySelector('.toggle-omemo');
|
|
|
|
|
expect(view.model.get('omemo_active')).toBe(undefined);
|
2019-08-05 01:39:57 +02:00
|
|
|
|
expect(toggle === null).toBe(false);
|
2018-12-13 09:48:43 +01:00
|
|
|
|
expect(u.hasClass('fa-unlock', toggle)).toBe(true);
|
|
|
|
|
expect(u.hasClass('fa-lock', toggle)).toBe(false);
|
|
|
|
|
expect(u.hasClass('disabled', toggle)).toBe(false);
|
|
|
|
|
expect(view.model.get('omemo_supported')).toBe(true);
|
|
|
|
|
|
|
|
|
|
toggle.click();
|
|
|
|
|
toggle = toolbar.querySelector('.toggle-omemo');
|
|
|
|
|
expect(view.model.get('omemo_active')).toBe(true);
|
|
|
|
|
expect(u.hasClass('fa-unlock', toggle)).toBe(false);
|
|
|
|
|
expect(u.hasClass('fa-lock', toggle)).toBe(true);
|
|
|
|
|
expect(u.hasClass('disabled', toggle)).toBe(false);
|
|
|
|
|
expect(view.model.get('omemo_supported')).toBe(true);
|
|
|
|
|
|
2019-06-03 07:58:51 +02:00
|
|
|
|
let contact_jid = 'newguy@montague.lit';
|
2018-12-13 09:48:43 +01:00
|
|
|
|
let stanza = $pres({
|
2019-06-03 07:58:51 +02:00
|
|
|
|
to: 'romeo@montague.lit/orchard',
|
|
|
|
|
from: 'lounge@montague.lit/newguy'
|
2018-12-13 09:48:43 +01:00
|
|
|
|
})
|
|
|
|
|
.c('x', {xmlns: Strophe.NS.MUC_USER})
|
|
|
|
|
.c('item', {
|
|
|
|
|
'affiliation': 'none',
|
2019-06-03 07:58:51 +02:00
|
|
|
|
'jid': 'newguy@montague.lit/_converse.js-290929789',
|
2018-12-13 09:48:43 +01:00
|
|
|
|
'role': 'participant'
|
|
|
|
|
}).tree();
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
|
2019-07-11 22:50:30 +02:00
|
|
|
|
let iq_stanza = await u.waitUntil(() => deviceListFetched(_converse, contact_jid));
|
2019-05-20 12:38:33 +02:00
|
|
|
|
expect(Strophe.serialize(iq_stanza)).toBe(
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`<iq from="romeo@montague.lit" id="${iq_stanza.getAttribute("id")}" to="${contact_jid}" type="get" xmlns="jabber:client">`+
|
2018-12-13 09:48:43 +01:00
|
|
|
|
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
|
|
|
|
`<items node="eu.siacs.conversations.axolotl.devicelist"/>`+
|
|
|
|
|
`</pubsub>`+
|
|
|
|
|
`</iq>`);
|
|
|
|
|
|
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': contact_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-12-13 09:48:43 +01:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {'xmlns': "http://jabber.org/protocol/pubsub"})
|
|
|
|
|
.c('items', {'node': "eu.siacs.conversations.axolotl.devicelist"})
|
|
|
|
|
.c('item', {'xmlns': "http://jabber.org/protocol/pubsub"}) // TODO: must have an id attribute
|
|
|
|
|
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
|
|
|
|
.c('device', {'id': '4e30f35051b7b8b42abe083742187228'}).up()
|
|
|
|
|
.c('device', {'id': 'ae890ac52d0df67ed7cfdf51b644e901'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => _converse.omemo_store);
|
2018-12-13 09:48:43 +01:00
|
|
|
|
expect(_converse.devicelists.length).toBe(2);
|
|
|
|
|
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => deviceListFetched(_converse, contact_jid));
|
2018-12-13 09:48:43 +01:00
|
|
|
|
const devicelist = _converse.devicelists.get(contact_jid);
|
|
|
|
|
expect(devicelist.devices.length).toBe(2);
|
|
|
|
|
expect(devicelist.devices.at(0).get('id')).toBe('4e30f35051b7b8b42abe083742187228');
|
|
|
|
|
expect(devicelist.devices.at(1).get('id')).toBe('ae890ac52d0df67ed7cfdf51b644e901');
|
|
|
|
|
|
|
|
|
|
expect(view.model.get('omemo_active')).toBe(true);
|
|
|
|
|
toggle = toolbar.querySelector('.toggle-omemo');
|
2019-08-05 01:39:57 +02:00
|
|
|
|
expect(toggle === null).toBe(false);
|
2018-12-13 09:48:43 +01:00
|
|
|
|
expect(u.hasClass('fa-unlock', toggle)).toBe(false);
|
|
|
|
|
expect(u.hasClass('fa-lock', toggle)).toBe(true);
|
|
|
|
|
expect(u.hasClass('disabled', toggle)).toBe(false);
|
|
|
|
|
expect(view.model.get('omemo_supported')).toBe(true);
|
|
|
|
|
|
|
|
|
|
// Test that the button gets disabled when the room becomes
|
|
|
|
|
// anonymous or semi-anonymous
|
2019-01-10 12:14:45 +01:00
|
|
|
|
view.model.features.save({'nonanonymous': false, 'semianonymous': true});
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => !view.model.get('omemo_supported'));
|
2018-12-13 09:48:43 +01:00
|
|
|
|
toggle = toolbar.querySelector('.toggle-omemo');
|
2019-08-05 01:39:57 +02:00
|
|
|
|
expect(toggle === null).toBe(true);
|
2018-12-13 09:48:43 +01:00
|
|
|
|
expect(view.model.get('omemo_supported')).toBe(false);
|
|
|
|
|
|
2019-01-10 12:14:45 +01:00
|
|
|
|
view.model.features.save({'nonanonymous': true, 'semianonymous': false});
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => view.model.get('omemo_supported'));
|
2018-12-13 09:48:43 +01:00
|
|
|
|
toggle = toolbar.querySelector('.toggle-omemo');
|
2019-08-05 01:39:57 +02:00
|
|
|
|
expect(toggle === null).toBe(false);
|
2018-12-13 09:48:43 +01:00
|
|
|
|
expect(u.hasClass('fa-unlock', toggle)).toBe(true);
|
|
|
|
|
expect(u.hasClass('fa-lock', toggle)).toBe(false);
|
|
|
|
|
expect(u.hasClass('disabled', toggle)).toBe(false);
|
|
|
|
|
|
|
|
|
|
// Test that the button gets disabled when the room becomes open
|
2019-01-10 12:14:45 +01:00
|
|
|
|
view.model.features.save({'membersonly': false, 'open': true});
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => !view.model.get('omemo_supported'));
|
2018-12-13 09:48:43 +01:00
|
|
|
|
toggle = toolbar.querySelector('.toggle-omemo');
|
2019-08-05 01:39:57 +02:00
|
|
|
|
expect(toggle === null).toBe(true);
|
2018-12-13 09:48:43 +01:00
|
|
|
|
|
2019-01-10 12:14:45 +01:00
|
|
|
|
view.model.features.save({'membersonly': true, 'open': false});
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => view.model.get('omemo_supported'));
|
2018-12-13 09:48:43 +01:00
|
|
|
|
toggle = toolbar.querySelector('.toggle-omemo');
|
2019-08-05 01:39:57 +02:00
|
|
|
|
expect(toggle === null).toBe(false);
|
2018-12-13 09:48:43 +01:00
|
|
|
|
expect(u.hasClass('fa-unlock', toggle)).toBe(true);
|
|
|
|
|
expect(u.hasClass('fa-lock', toggle)).toBe(false);
|
|
|
|
|
expect(u.hasClass('disabled', toggle)).toBe(false);
|
|
|
|
|
expect(view.model.get('omemo_supported')).toBe(true);
|
|
|
|
|
expect(view.model.get('omemo_active')).toBe(false);
|
|
|
|
|
|
|
|
|
|
toggle.click();
|
|
|
|
|
expect(view.model.get('omemo_active')).toBe(true);
|
|
|
|
|
|
|
|
|
|
// Someone enters the room who doesn't have OMEMO support, while we
|
|
|
|
|
// have OMEMO activated...
|
2019-06-03 07:58:51 +02:00
|
|
|
|
contact_jid = 'oldguy@montague.lit';
|
2018-12-13 09:48:43 +01:00
|
|
|
|
stanza = $pres({
|
2019-06-03 07:58:51 +02:00
|
|
|
|
to: 'romeo@montague.lit/orchard',
|
|
|
|
|
from: 'lounge@montague.lit/oldguy'
|
2018-12-13 09:48:43 +01:00
|
|
|
|
})
|
|
|
|
|
.c('x', {xmlns: Strophe.NS.MUC_USER})
|
|
|
|
|
.c('item', {
|
|
|
|
|
'affiliation': 'none',
|
|
|
|
|
'jid': `${contact_jid}/_converse.js-290929788`,
|
|
|
|
|
'role': 'participant'
|
|
|
|
|
}).tree();
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
iq_stanza = await u.waitUntil(() => deviceListFetched(_converse, contact_jid));
|
2019-05-20 12:38:33 +02:00
|
|
|
|
expect(Strophe.serialize(iq_stanza)).toBe(
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`<iq from="romeo@montague.lit" id="${iq_stanza.getAttribute("id")}" to="${contact_jid}" type="get" xmlns="jabber:client">`+
|
2018-12-13 09:48:43 +01:00
|
|
|
|
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
|
|
|
|
`<items node="eu.siacs.conversations.axolotl.devicelist"/>`+
|
|
|
|
|
`</pubsub>`+
|
|
|
|
|
`</iq>`);
|
|
|
|
|
|
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': contact_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-12-13 09:48:43 +01:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'error'
|
|
|
|
|
}).c('error', {'type': 'cancel'})
|
|
|
|
|
.c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => !view.model.get('omemo_supported'));
|
2018-12-13 09:48:43 +01:00
|
|
|
|
|
2019-08-12 20:16:34 +02:00
|
|
|
|
expect(view.el.querySelector('.chat-error').textContent.trim()).toBe(
|
2018-12-13 09:48:43 +01:00
|
|
|
|
"oldguy doesn't appear to have a client that supports OMEMO. "+
|
|
|
|
|
"Encrypted chat will no longer be possible in this grouchat."
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
toggle = toolbar.querySelector('.toggle-omemo');
|
2019-08-05 01:39:57 +02:00
|
|
|
|
expect(toggle === null).toBe(false);
|
2018-12-13 09:48:43 +01:00
|
|
|
|
expect(u.hasClass('fa-unlock', toggle)).toBe(true);
|
|
|
|
|
expect(u.hasClass('fa-lock', toggle)).toBe(false);
|
|
|
|
|
expect(u.hasClass('disabled', toggle)).toBe(true);
|
|
|
|
|
|
|
|
|
|
expect( _converse.chatboxviews.el.querySelector('.modal-body p')).toBe(null);
|
|
|
|
|
toggle.click();
|
|
|
|
|
const msg = _converse.chatboxviews.el.querySelector('.modal-body p');
|
|
|
|
|
expect(msg.textContent).toBe(
|
|
|
|
|
'Cannot use end-to-end encryption in this groupchat, '+
|
|
|
|
|
'either the groupchat has some anonymity or not all participants support OMEMO.');
|
|
|
|
|
done();
|
|
|
|
|
}));
|
|
|
|
|
|
2018-08-26 19:33:34 +02:00
|
|
|
|
|
2018-07-22 16:12:36 +02:00
|
|
|
|
it("shows OMEMO device fingerprints in the user details modal",
|
2019-02-12 14:21:45 +01:00
|
|
|
|
mock.initConverse(
|
2018-08-04 08:39:14 +02:00
|
|
|
|
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
2018-10-15 23:18:06 +02:00
|
|
|
|
async function (done, _converse) {
|
2018-07-22 16:12:36 +02:00
|
|
|
|
|
2018-12-19 08:14:58 +01:00
|
|
|
|
await test_utils.waitUntilDiscoConfirmed(
|
|
|
|
|
_converse, _converse.bare_jid,
|
|
|
|
|
[{'category': 'pubsub', 'type': 'pep'}],
|
|
|
|
|
['http://jabber.org/protocol/pubsub#publish-options']
|
|
|
|
|
);
|
|
|
|
|
|
2018-07-22 16:12:36 +02:00
|
|
|
|
test_utils.createContacts(_converse, 'current', 1);
|
2019-03-29 21:10:45 +01:00
|
|
|
|
_converse.api.trigger('rosterContactsFetched');
|
2019-06-03 07:58:51 +02:00
|
|
|
|
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
2018-10-15 23:18:06 +02:00
|
|
|
|
await test_utils.openChatBoxFor(_converse, contact_jid)
|
|
|
|
|
// We simply emit, to avoid doing all the setup work
|
2019-03-29 21:10:45 +01:00
|
|
|
|
_converse.api.trigger('OMEMOInitialized');
|
2018-10-15 23:18:06 +02:00
|
|
|
|
|
|
|
|
|
const view = _converse.chatboxviews.get(contact_jid);
|
|
|
|
|
const show_modal_button = view.el.querySelector('.show-user-details-modal');
|
|
|
|
|
show_modal_button.click();
|
|
|
|
|
const modal = view.user_details_modal;
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => u.isVisible(modal.el), 1000);
|
|
|
|
|
let iq_stanza = await u.waitUntil(() => deviceListFetched(_converse, contact_jid));
|
2019-05-20 12:38:33 +02:00
|
|
|
|
expect(Strophe.serialize(iq_stanza)).toBe(
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`<iq from="romeo@montague.lit" id="${iq_stanza.getAttribute("id")}" to="mercutio@montague.lit" type="get" xmlns="jabber:client">`+
|
2018-10-15 23:18:06 +02:00
|
|
|
|
`<pubsub xmlns="http://jabber.org/protocol/pubsub"><items node="eu.siacs.conversations.axolotl.devicelist"/></pubsub>`+
|
|
|
|
|
`</iq>`);
|
|
|
|
|
let stanza = $iq({
|
|
|
|
|
'from': contact_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {'xmlns': "http://jabber.org/protocol/pubsub"})
|
|
|
|
|
.c('items', {'node': "eu.siacs.conversations.axolotl.devicelist"})
|
|
|
|
|
.c('item', {'xmlns': "http://jabber.org/protocol/pubsub"}) // TODO: must have an id attribute
|
|
|
|
|
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
|
|
|
|
.c('device', {'id': '555'});
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => u.isVisible(modal.el), 1000);
|
|
|
|
|
iq_stanza = await u.waitUntil(() => bundleFetched(_converse, contact_jid, '555'));
|
2019-05-20 12:38:33 +02:00
|
|
|
|
expect(Strophe.serialize(iq_stanza)).toBe(
|
2019-06-03 07:58:51 +02:00
|
|
|
|
`<iq from="romeo@montague.lit" id="${iq_stanza.getAttribute("id")}" to="mercutio@montague.lit" type="get" xmlns="jabber:client">`+
|
2018-10-15 23:18:06 +02:00
|
|
|
|
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
|
|
|
|
`<items node="eu.siacs.conversations.axolotl.bundles:555"/>`+
|
|
|
|
|
`</pubsub>`+
|
|
|
|
|
`</iq>`);
|
|
|
|
|
stanza = $iq({
|
|
|
|
|
'from': contact_jid,
|
2019-05-20 12:38:33 +02:00
|
|
|
|
'id': iq_stanza.getAttribute('id'),
|
2018-10-15 23:18:06 +02:00
|
|
|
|
'to': _converse.bare_jid,
|
|
|
|
|
'type': 'result',
|
|
|
|
|
}).c('pubsub', {
|
|
|
|
|
'xmlns': 'http://jabber.org/protocol/pubsub'
|
|
|
|
|
}).c('items', {'node': "eu.siacs.conversations.axolotl.bundles:555"})
|
|
|
|
|
.c('item')
|
|
|
|
|
.c('bundle', {'xmlns': 'eu.siacs.conversations.axolotl'})
|
|
|
|
|
.c('signedPreKeyPublic', {'signedPreKeyId': '4223'}).t(btoa('1111')).up()
|
|
|
|
|
.c('signedPreKeySignature').t(btoa('2222')).up()
|
|
|
|
|
.c('identityKey').t('BQmHEOHjsYm3w5M8VqxAtqJmLCi7CaxxsdZz6G0YpuMI').up()
|
|
|
|
|
.c('prekeys')
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '1'}).t(btoa('1001')).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '2'}).t(btoa('1002')).up()
|
|
|
|
|
.c('preKeyPublic', {'preKeyId': '3'}).t(btoa('1003'));
|
|
|
|
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
|
|
|
|
|
2019-07-11 22:50:30 +02:00
|
|
|
|
await u.waitUntil(() => modal.el.querySelectorAll('.fingerprints .fingerprint').length);
|
2018-10-15 23:18:06 +02:00
|
|
|
|
expect(modal.el.querySelectorAll('.fingerprints .fingerprint').length).toBe(1);
|
|
|
|
|
const el = modal.el.querySelector('.fingerprints .fingerprint');
|
|
|
|
|
expect(el.textContent.trim()).toBe(
|
|
|
|
|
u.formatFingerprint(u.arrayBufferToHex(u.base64ToArrayBuffer('BQmHEOHjsYm3w5M8VqxAtqJmLCi7CaxxsdZz6G0YpuMI')))
|
|
|
|
|
);
|
|
|
|
|
expect(modal.el.querySelectorAll('input[type="radio"]').length).toBe(2);
|
|
|
|
|
|
|
|
|
|
const devicelist = _converse.devicelists.get(contact_jid);
|
|
|
|
|
expect(devicelist.devices.get('555').get('trusted')).toBe(0);
|
|
|
|
|
|
|
|
|
|
let trusted_radio = modal.el.querySelector('input[type="radio"][name="555"][value="1"]');
|
|
|
|
|
expect(trusted_radio.checked).toBe(true);
|
|
|
|
|
|
|
|
|
|
let untrusted_radio = modal.el.querySelector('input[type="radio"][name="555"][value="-1"]');
|
|
|
|
|
expect(untrusted_radio.checked).toBe(false);
|
|
|
|
|
|
|
|
|
|
// Test that the device can be set to untrusted
|
|
|
|
|
untrusted_radio.click();
|
|
|
|
|
trusted_radio = document.querySelector('input[type="radio"][name="555"][value="1"]');
|
|
|
|
|
expect(trusted_radio.hasAttribute('checked')).toBe(false);
|
|
|
|
|
expect(devicelist.devices.get('555').get('trusted')).toBe(-1);
|
|
|
|
|
|
|
|
|
|
untrusted_radio = document.querySelector('input[type="radio"][name="555"][value="-1"]');
|
|
|
|
|
expect(untrusted_radio.hasAttribute('checked')).toBe(true);
|
|
|
|
|
|
|
|
|
|
trusted_radio.click();
|
|
|
|
|
expect(devicelist.devices.get('555').get('trusted')).toBe(1);
|
|
|
|
|
done();
|
2018-07-22 16:12:36 +02:00
|
|
|
|
}));
|
2018-05-12 19:37:44 +02:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe("A chatbox with an active OMEMO session", function() {
|
|
|
|
|
|
|
|
|
|
it("will not show the spoiler toolbar button",
|
2019-02-12 14:21:45 +01:00
|
|
|
|
mock.initConverse(
|
2018-05-12 19:37:44 +02:00
|
|
|
|
null, ['rosterGroupsFetched'], {},
|
|
|
|
|
function (done, _converse) {
|
|
|
|
|
// TODO
|
|
|
|
|
done()
|
|
|
|
|
}));
|
|
|
|
|
});
|
|
|
|
|
}));
|