Add a button for regenerating your OMEMO device bundle
This commit is contained in:
parent
c2e549e7d7
commit
3b60ced39c
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
- Error `FATAL: TypeError: Cannot read property 'extend' of undefined` when using `embedded` view mode.
|
- Error `FATAL: TypeError: Cannot read property 'extend' of undefined` when using `embedded` view mode.
|
||||||
- Default paths in converse-notifications.js are now relative
|
- Default paths in converse-notifications.js are now relative
|
||||||
|
- Add a button to regenerate OMEMO keys
|
||||||
- #1188 Feature request: drag and drop file to HTTP Upload
|
- #1188 Feature request: drag and drop file to HTTP Upload
|
||||||
- #1268 Switch from SASS variables to CSS custom properties
|
- #1268 Switch from SASS variables to CSS custom properties
|
||||||
- #1278 Replace the default avatar with a SVG version
|
- #1278 Replace the default avatar with a SVG version
|
||||||
|
|
130
dist/converse.js
vendored
130
dist/converse.js
vendored
|
@ -65359,6 +65359,7 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
|
||||||
ProfileModal: {
|
ProfileModal: {
|
||||||
events: {
|
events: {
|
||||||
'change input.select-all': 'selectAll',
|
'change input.select-all': 'selectAll',
|
||||||
|
'click .generate-bundle': 'generateOMEMODeviceBundle',
|
||||||
'submit .fingerprint-removal': 'removeSelectedFingerprints'
|
'submit .fingerprint-removal': 'removeSelectedFingerprints'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -65368,6 +65369,7 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
|
||||||
this.devicelist = _converse.devicelists.get(_converse.bare_jid);
|
this.devicelist = _converse.devicelists.get(_converse.bare_jid);
|
||||||
this.devicelist.devices.on('change:bundle', this.debouncedRender, this);
|
this.devicelist.devices.on('change:bundle', this.debouncedRender, this);
|
||||||
this.devicelist.devices.on('reset', this.debouncedRender, this);
|
this.devicelist.devices.on('reset', this.debouncedRender, this);
|
||||||
|
this.devicelist.devices.on('reset', this.debouncedRender, this);
|
||||||
this.devicelist.devices.on('remove', this.debouncedRender, this);
|
this.devicelist.devices.on('remove', this.debouncedRender, this);
|
||||||
this.devicelist.devices.on('add', this.debouncedRender, this);
|
this.devicelist.devices.on('add', this.debouncedRender, this);
|
||||||
return this.__super__.initialize.apply(this, arguments);
|
return this.__super__.initialize.apply(this, arguments);
|
||||||
|
@ -65377,7 +65379,10 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
|
||||||
const _converse = this.__super__._converse,
|
const _converse = this.__super__._converse,
|
||||||
device_id = _converse.omemo_store.get('device_id');
|
device_id = _converse.omemo_store.get('device_id');
|
||||||
|
|
||||||
this.current_device = this.devicelist.devices.get(device_id);
|
if (device_id) {
|
||||||
|
this.current_device = this.devicelist.devices.get(device_id);
|
||||||
|
}
|
||||||
|
|
||||||
this.other_devices = this.devicelist.devices.filter(d => d.get('id') !== device_id);
|
this.other_devices = this.devicelist.devices.filter(d => d.get('id') !== device_id);
|
||||||
|
|
||||||
if (this.__super__.beforeRender) {
|
if (this.__super__.beforeRender) {
|
||||||
|
@ -65410,6 +65415,17 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
|
||||||
|
|
||||||
_converse.api.alert.show(Strophe.LogLevel.ERROR, __('Error'), [__('Sorry, an error occurred while trying to remove the devices.')]);
|
_converse.api.alert.show(Strophe.LogLevel.ERROR, __('Error'), [__('Sorry, an error occurred while trying to remove the devices.')]);
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
generateOMEMODeviceBundle(ev) {
|
||||||
|
const _converse = this.__super__._converse,
|
||||||
|
__ = _converse.__,
|
||||||
|
api = _converse.api;
|
||||||
|
ev.preventDefault();
|
||||||
|
|
||||||
|
if (confirm(__("Are you sure you want to generate new OMEMO keys?" + "This will remove your old keys and all previously encrypted messages will no longer be ecryptable on this device."))) {
|
||||||
|
api.omemo.bundle.generate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
@ -65453,27 +65469,26 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
|
||||||
}).then(() => this.buildSessions(devices));
|
}).then(() => this.buildSessions(devices));
|
||||||
},
|
},
|
||||||
|
|
||||||
buildSession(device) {
|
async buildSession(device) {
|
||||||
const _converse = this.__super__._converse,
|
const _converse = this.__super__._converse,
|
||||||
address = new libsignal.SignalProtocolAddress(device.get('jid'), device.get('id')),
|
address = new libsignal.SignalProtocolAddress(device.get('jid'), device.get('id')),
|
||||||
sessionBuilder = new libsignal.SessionBuilder(_converse.omemo_store, address),
|
sessionBuilder = new libsignal.SessionBuilder(_converse.omemo_store, address),
|
||||||
prekey = device.getRandomPreKey();
|
prekey = device.getRandomPreKey(),
|
||||||
return device.getBundle().then(bundle => {
|
bundle = await device.getBundle();
|
||||||
return sessionBuilder.processPreKey({
|
return sessionBuilder.processPreKey({
|
||||||
'registrationId': parseInt(device.get('id'), 10),
|
'registrationId': parseInt(device.get('id'), 10),
|
||||||
'identityKey': u.base64ToArrayBuffer(bundle.identity_key),
|
'identityKey': u.base64ToArrayBuffer(bundle.identity_key),
|
||||||
'signedPreKey': {
|
'signedPreKey': {
|
||||||
'keyId': bundle.signed_prekey.id,
|
'keyId': bundle.signed_prekey.id,
|
||||||
// <Number>
|
// <Number>
|
||||||
'publicKey': u.base64ToArrayBuffer(bundle.signed_prekey.public_key),
|
'publicKey': u.base64ToArrayBuffer(bundle.signed_prekey.public_key),
|
||||||
'signature': u.base64ToArrayBuffer(bundle.signed_prekey.signature)
|
'signature': u.base64ToArrayBuffer(bundle.signed_prekey.signature)
|
||||||
},
|
},
|
||||||
'preKey': {
|
'preKey': {
|
||||||
'keyId': prekey.id,
|
'keyId': prekey.id,
|
||||||
// <Number>
|
// <Number>
|
||||||
'publicKey': u.base64ToArrayBuffer(prekey.key)
|
'publicKey': u.base64ToArrayBuffer(prekey.key)
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -65792,20 +65807,20 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
|
||||||
|
|
||||||
_converse.NUM_PREKEYS = 100; // Set here so that tests can override
|
_converse.NUM_PREKEYS = 100; // Set here so that tests can override
|
||||||
|
|
||||||
function generateFingerprint(device) {
|
async function generateFingerprint(device) {
|
||||||
if (_.get(device.get('bundle'), 'fingerprint')) {
|
if (_.get(device.get('bundle'), 'fingerprint')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return device.getBundle().then(bundle => {
|
const bundle = await device.getBundle();
|
||||||
bundle['fingerprint'] = u.arrayBufferToHex(u.base64ToArrayBuffer(bundle['identity_key']));
|
bundle['fingerprint'] = u.arrayBufferToHex(u.base64ToArrayBuffer(bundle['identity_key']));
|
||||||
device.save('bundle', bundle);
|
device.save('bundle', bundle);
|
||||||
device.trigger('change:bundle'); // Doesn't get triggered automatically due to pass-by-reference
|
device.trigger('change:bundle'); // Doesn't get triggered automatically due to pass-by-reference
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_converse.generateFingerprints = function (jid) {
|
_converse.generateFingerprints = async function (jid) {
|
||||||
return _converse.getDevicesForContact(jid).then(devices => Promise.all(devices.map(d => generateFingerprint(d))));
|
const devices = await _converse.getDevicesForContact(jid);
|
||||||
|
return Promise.all(devices.map(d => generateFingerprint(d)));
|
||||||
};
|
};
|
||||||
|
|
||||||
_converse.getDeviceForContact = function (jid, device_id) {
|
_converse.getDeviceForContact = function (jid, device_id) {
|
||||||
|
@ -66452,6 +66467,61 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
|
||||||
_converse.api.listen.on('profileModalInitialized', contact => {
|
_converse.api.listen.on('profileModalInitialized', contact => {
|
||||||
_converse.generateFingerprints(_converse.bare_jid).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
_converse.generateFingerprints(_converse.bare_jid).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
||||||
});
|
});
|
||||||
|
/************************ BEGIN API ************************/
|
||||||
|
|
||||||
|
|
||||||
|
_.extend(_converse.api, {
|
||||||
|
/**
|
||||||
|
* The "omemo" namespace groups methods relevant to OMEMO
|
||||||
|
* encryption.
|
||||||
|
*
|
||||||
|
* @namespace _converse.api.omemo
|
||||||
|
* @memberOf _converse.api
|
||||||
|
*/
|
||||||
|
'omemo': {
|
||||||
|
/**
|
||||||
|
* The "bundle" namespace groups methods relevant to the user's
|
||||||
|
* OMEMO bundle.
|
||||||
|
*
|
||||||
|
* @namespace _converse.api.omemo.bundle
|
||||||
|
* @memberOf _converse.api.omemo
|
||||||
|
*/
|
||||||
|
'bundle': {
|
||||||
|
/**
|
||||||
|
* Lets you generate a new OMEMO device bundle
|
||||||
|
*
|
||||||
|
* @method _converse.api.omemo.bundle.generate
|
||||||
|
* @returns {promise} Promise which resolves once we have a result from the server.
|
||||||
|
*/
|
||||||
|
'generate': async () => {
|
||||||
|
// Remove current device
|
||||||
|
const devicelist = _converse.devicelists.get(_converse.bare_jid),
|
||||||
|
device_id = _converse.omemo_store.get('device_id');
|
||||||
|
|
||||||
|
if (device_id) {
|
||||||
|
const device = devicelist.devices.get(device_id);
|
||||||
|
|
||||||
|
_converse.omemo_store.unset(device_id);
|
||||||
|
|
||||||
|
if (device) {
|
||||||
|
await new Promise(done => device.destroy({
|
||||||
|
'success': done,
|
||||||
|
'error': done
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
devicelist.devices.trigger('remove');
|
||||||
|
} // Generate new bundle and publish
|
||||||
|
|
||||||
|
|
||||||
|
await _converse.omemo_store.generateBundle();
|
||||||
|
await devicelist.publishDevices();
|
||||||
|
const device = devicelist.devices.get(_converse.omemo_store.get('device_id'));
|
||||||
|
return generateFingerprint(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -66518,8 +66588,8 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_4__["default"].plugins
|
||||||
__ = _converse.__;
|
__ = _converse.__;
|
||||||
_converse.ProfileModal = _converse.BootstrapModal.extend({
|
_converse.ProfileModal = _converse.BootstrapModal.extend({
|
||||||
events: {
|
events: {
|
||||||
'click .change-avatar': "openFileSelection",
|
|
||||||
'change input[type="file"': "updateFilePreview",
|
'change input[type="file"': "updateFilePreview",
|
||||||
|
'click .change-avatar': "openFileSelection",
|
||||||
'submit .profile-form': 'onFormSubmitted'
|
'submit .profile-form': 'onFormSubmitted'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -102683,7 +102753,9 @@ __e(o.utils.formatFingerprint(o.view.current_device.get('bundle').fingerprint))
|
||||||
} else {;
|
} else {;
|
||||||
__p += '\n <span class="spinner fa fa-spinner centered"/>\n ';
|
__p += '\n <span class="spinner fa fa-spinner centered"/>\n ';
|
||||||
} ;
|
} ;
|
||||||
__p += '\n </li>\n </ul>\n ';
|
__p += '\n </li>\n </ul>\n <div class="form-group">\n <button type="button" class="generate-bundle btn btn-danger">' +
|
||||||
|
__e(o.__('Generate new keys and fingerprint')) +
|
||||||
|
'</button>\n </div>\n\n ';
|
||||||
if (o.view.other_devices.length) { ;
|
if (o.view.other_devices.length) { ;
|
||||||
__p += '\n <ul class="list-group fingerprints">\n <li class="list-group-item nopadding active">\n <label>\n <input type="checkbox" class="select-all" title="' +
|
__p += '\n <ul class="list-group fingerprints">\n <li class="list-group-item nopadding active">\n <label>\n <input type="checkbox" class="select-all" title="' +
|
||||||
__e(o.__('Select all')) +
|
__e(o.__('Select all')) +
|
||||||
|
|
|
@ -68,6 +68,7 @@ converse.plugins.add('converse-omemo', {
|
||||||
ProfileModal: {
|
ProfileModal: {
|
||||||
events: {
|
events: {
|
||||||
'change input.select-all': 'selectAll',
|
'change input.select-all': 'selectAll',
|
||||||
|
'click .generate-bundle': 'generateOMEMODeviceBundle',
|
||||||
'submit .fingerprint-removal': 'removeSelectedFingerprints'
|
'submit .fingerprint-removal': 'removeSelectedFingerprints'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -77,6 +78,7 @@ converse.plugins.add('converse-omemo', {
|
||||||
this.devicelist = _converse.devicelists.get(_converse.bare_jid);
|
this.devicelist = _converse.devicelists.get(_converse.bare_jid);
|
||||||
this.devicelist.devices.on('change:bundle', this.debouncedRender, this);
|
this.devicelist.devices.on('change:bundle', this.debouncedRender, this);
|
||||||
this.devicelist.devices.on('reset', this.debouncedRender, this);
|
this.devicelist.devices.on('reset', this.debouncedRender, this);
|
||||||
|
this.devicelist.devices.on('reset', this.debouncedRender, this);
|
||||||
this.devicelist.devices.on('remove', this.debouncedRender, this);
|
this.devicelist.devices.on('remove', this.debouncedRender, this);
|
||||||
this.devicelist.devices.on('add', this.debouncedRender, this);
|
this.devicelist.devices.on('add', this.debouncedRender, this);
|
||||||
return this.__super__.initialize.apply(this, arguments);
|
return this.__super__.initialize.apply(this, arguments);
|
||||||
|
@ -85,7 +87,10 @@ converse.plugins.add('converse-omemo', {
|
||||||
beforeRender () {
|
beforeRender () {
|
||||||
const { _converse } = this.__super__,
|
const { _converse } = this.__super__,
|
||||||
device_id = _converse.omemo_store.get('device_id');
|
device_id = _converse.omemo_store.get('device_id');
|
||||||
this.current_device = this.devicelist.devices.get(device_id);
|
|
||||||
|
if (device_id) {
|
||||||
|
this.current_device = this.devicelist.devices.get(device_id);
|
||||||
|
}
|
||||||
this.other_devices = this.devicelist.devices.filter(d => (d.get('id') !== device_id));
|
this.other_devices = this.devicelist.devices.filter(d => (d.get('id') !== device_id));
|
||||||
if (this.__super__.beforeRender) {
|
if (this.__super__.beforeRender) {
|
||||||
return this.__super__.beforeRender.apply(this, arguments);
|
return this.__super__.beforeRender.apply(this, arguments);
|
||||||
|
@ -118,6 +123,18 @@ converse.plugins.add('converse-omemo', {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
generateOMEMODeviceBundle (ev) {
|
||||||
|
const { _converse } = this.__super__,
|
||||||
|
{ __, api } = _converse;
|
||||||
|
ev.preventDefault();
|
||||||
|
if (confirm(__(
|
||||||
|
"Are you sure you want to generate new OMEMO keys?" +
|
||||||
|
"This will remove your old keys and all previously encrypted messages will no longer be ecryptable on this device.")
|
||||||
|
)) {
|
||||||
|
api.omemo.bundle.generate();
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
UserDetailsModal: {
|
UserDetailsModal: {
|
||||||
|
@ -475,20 +492,19 @@ converse.plugins.add('converse-omemo', {
|
||||||
|
|
||||||
_converse.NUM_PREKEYS = 100; // Set here so that tests can override
|
_converse.NUM_PREKEYS = 100; // Set here so that tests can override
|
||||||
|
|
||||||
function generateFingerprint (device) {
|
async function generateFingerprint (device) {
|
||||||
if (_.get(device.get('bundle'), 'fingerprint')) {
|
if (_.get(device.get('bundle'), 'fingerprint')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return device.getBundle().then(bundle => {
|
const bundle = await device.getBundle();
|
||||||
bundle['fingerprint'] = u.arrayBufferToHex(u.base64ToArrayBuffer(bundle['identity_key']));
|
bundle['fingerprint'] = u.arrayBufferToHex(u.base64ToArrayBuffer(bundle['identity_key']));
|
||||||
device.save('bundle', bundle);
|
device.save('bundle', bundle);
|
||||||
device.trigger('change:bundle'); // Doesn't get triggered automatically due to pass-by-reference
|
device.trigger('change:bundle'); // Doesn't get triggered automatically due to pass-by-reference
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_converse.generateFingerprints = function (jid) {
|
_converse.generateFingerprints = async function (jid) {
|
||||||
return _converse.getDevicesForContact(jid)
|
const devices = await _converse.getDevicesForContact(jid)
|
||||||
.then(devices => Promise.all(devices.map(d => generateFingerprint(d))))
|
return Promise.all(devices.map(d => generateFingerprint(d)));
|
||||||
}
|
}
|
||||||
|
|
||||||
_converse.getDeviceForContact = function (jid, device_id) {
|
_converse.getDeviceForContact = function (jid, device_id) {
|
||||||
|
@ -1044,6 +1060,52 @@ converse.plugins.add('converse-omemo', {
|
||||||
_converse.api.listen.on('profileModalInitialized', (contact) => {
|
_converse.api.listen.on('profileModalInitialized', (contact) => {
|
||||||
_converse.generateFingerprints(_converse.bare_jid).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
_converse.generateFingerprints(_converse.bare_jid).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/************************ BEGIN API ************************/
|
||||||
|
_.extend(_converse.api, {
|
||||||
|
/**
|
||||||
|
* The "omemo" namespace groups methods relevant to OMEMO
|
||||||
|
* encryption.
|
||||||
|
*
|
||||||
|
* @namespace _converse.api.omemo
|
||||||
|
* @memberOf _converse.api
|
||||||
|
*/
|
||||||
|
'omemo': {
|
||||||
|
/**
|
||||||
|
* The "bundle" namespace groups methods relevant to the user's
|
||||||
|
* OMEMO bundle.
|
||||||
|
*
|
||||||
|
* @namespace _converse.api.omemo.bundle
|
||||||
|
* @memberOf _converse.api.omemo
|
||||||
|
*/
|
||||||
|
'bundle': {
|
||||||
|
/**
|
||||||
|
* Lets you generate a new OMEMO device bundle
|
||||||
|
*
|
||||||
|
* @method _converse.api.omemo.bundle.generate
|
||||||
|
* @returns {promise} Promise which resolves once we have a result from the server.
|
||||||
|
*/
|
||||||
|
'generate': async () => {
|
||||||
|
// Remove current device
|
||||||
|
const devicelist = _converse.devicelists.get(_converse.bare_jid),
|
||||||
|
device_id = _converse.omemo_store.get('device_id');
|
||||||
|
if (device_id) {
|
||||||
|
const device = devicelist.devices.get(device_id);
|
||||||
|
_converse.omemo_store.unset(device_id);
|
||||||
|
if (device) {
|
||||||
|
await new Promise(done => device.destroy({'success': done, 'error': done}));
|
||||||
|
}
|
||||||
|
devicelist.devices.trigger('remove');
|
||||||
|
}
|
||||||
|
// Generate new bundle and publish
|
||||||
|
await _converse.omemo_store.generateBundle();
|
||||||
|
await devicelist.publishDevices();
|
||||||
|
const device = devicelist.devices.get(_converse.omemo_store.get('device_id'));
|
||||||
|
return generateFingerprint(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,8 @@ converse.plugins.add('converse-profile', {
|
||||||
|
|
||||||
_converse.ProfileModal = _converse.BootstrapModal.extend({
|
_converse.ProfileModal = _converse.BootstrapModal.extend({
|
||||||
events: {
|
events: {
|
||||||
'click .change-avatar': "openFileSelection",
|
|
||||||
'change input[type="file"': "updateFilePreview",
|
'change input[type="file"': "updateFilePreview",
|
||||||
|
'click .change-avatar': "openFileSelection",
|
||||||
'submit .profile-form': 'onFormSubmitted'
|
'submit .profile-form': 'onFormSubmitted'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,10 @@
|
||||||
{[ } ]}
|
{[ } ]}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="button" class="generate-bundle btn btn-danger">{{{o.__('Generate new keys and fingerprint')}}}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
{[ if (o.view.other_devices.length) { ]}
|
{[ if (o.view.other_devices.length) { ]}
|
||||||
<ul class="list-group fingerprints">
|
<ul class="list-group fingerprints">
|
||||||
<li class="list-group-item nopadding active">
|
<li class="list-group-item nopadding active">
|
||||||
|
|
Loading…
Reference in New Issue
Block a user