Update safety number change warning dialog
This commit is contained in:
parent
e87a0103cc
commit
5b83485c89
38 changed files with 1221 additions and 425 deletions
|
@ -451,9 +451,12 @@
|
|||
|
||||
const result = {
|
||||
id: this.id,
|
||||
uuid: this.get('uuid'),
|
||||
e164: this.get('e164'),
|
||||
|
||||
isArchived: this.get('isArchived'),
|
||||
isBlocked: this.isBlocked(),
|
||||
isVerified: this.isVerified(),
|
||||
activeAt: this.get('active_at'),
|
||||
avatarPath: this.getAvatarPath(),
|
||||
color,
|
||||
|
|
|
@ -40,6 +40,9 @@ const {
|
|||
MessageDetail,
|
||||
} = require('../../ts/components/conversation/MessageDetail');
|
||||
const { Quote } = require('../../ts/components/conversation/Quote');
|
||||
const {
|
||||
SafetyNumberChangeDialog,
|
||||
} = require('../../ts/components/SafetyNumberChangeDialog');
|
||||
const {
|
||||
StagedLinkPreview,
|
||||
} = require('../../ts/components/conversation/StagedLinkPreview');
|
||||
|
@ -51,6 +54,9 @@ const {
|
|||
} = require('../../ts/state/roots/createCompositionArea');
|
||||
const { createCallManager } = require('../../ts/state/roots/createCallManager');
|
||||
const { createLeftPane } = require('../../ts/state/roots/createLeftPane');
|
||||
const {
|
||||
createSafetyNumberViewer,
|
||||
} = require('../../ts/state/roots/createSafetyNumberViewer');
|
||||
const {
|
||||
createStickerManager,
|
||||
} = require('../../ts/state/roots/createStickerManager');
|
||||
|
@ -274,6 +280,7 @@ exports.setup = (options = {}) => {
|
|||
MediaGallery,
|
||||
MessageDetail,
|
||||
Quote,
|
||||
SafetyNumberChangeDialog,
|
||||
StagedLinkPreview,
|
||||
Types: {
|
||||
Message: MediaGalleryMessage,
|
||||
|
@ -284,6 +291,7 @@ exports.setup = (options = {}) => {
|
|||
createCallManager,
|
||||
createCompositionArea,
|
||||
createLeftPane,
|
||||
createSafetyNumberViewer,
|
||||
createShortcutGuideModal,
|
||||
createStickerManager,
|
||||
createStickerPreviewModal,
|
||||
|
|
|
@ -2502,33 +2502,17 @@
|
|||
|
||||
showSendAnywayDialog(contacts) {
|
||||
return new Promise(resolve => {
|
||||
let message;
|
||||
const isUnverified = this.model.isUnverified();
|
||||
|
||||
if (contacts.length > 1) {
|
||||
if (isUnverified) {
|
||||
message = i18n('changedSinceVerifiedMultiple');
|
||||
} else {
|
||||
message = i18n('changedRecentlyMultiple');
|
||||
}
|
||||
} else {
|
||||
const contactName = contacts.at(0).getTitle();
|
||||
if (isUnverified) {
|
||||
message = i18n('changedSinceVerified', [contactName, contactName]);
|
||||
} else {
|
||||
message = i18n('changedRecently', [contactName, contactName]);
|
||||
}
|
||||
}
|
||||
|
||||
const dialog = new Whisper.ConfirmationDialogView({
|
||||
message,
|
||||
okText: i18n('sendAnyway'),
|
||||
resolve: () => resolve(true),
|
||||
reject: () => resolve(false),
|
||||
const dialog = new Whisper.SafetyNumberChangeDialogView({
|
||||
contacts,
|
||||
reject: () => {
|
||||
resolve(false);
|
||||
},
|
||||
resolve: () => {
|
||||
resolve(true);
|
||||
},
|
||||
});
|
||||
|
||||
this.$el.prepend(dialog.el);
|
||||
dialog.focusCancel();
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global Whisper, textsecure, QRCode, dcodeIO, libsignal, i18n, _ */
|
||||
/* global Whisper, Signal */
|
||||
|
||||
/* eslint-disable more/no-then */
|
||||
|
||||
|
@ -9,152 +9,18 @@
|
|||
window.Whisper = window.Whisper || {};
|
||||
|
||||
Whisper.KeyVerificationPanelView = Whisper.View.extend({
|
||||
className: 'key-verification panel',
|
||||
className: 'panel',
|
||||
templateName: 'key-verification',
|
||||
events: {
|
||||
'click button.verify': 'toggleVerified',
|
||||
},
|
||||
initialize(options) {
|
||||
this.ourNumber = textsecure.storage.user.getNumber();
|
||||
this.ourUuid = textsecure.storage.user.getUuid();
|
||||
if (options.newKey) {
|
||||
this.theirKey = options.newKey;
|
||||
}
|
||||
|
||||
this.loadTheirKey();
|
||||
this.loadOurKey();
|
||||
|
||||
this.render();
|
||||
if (options.onLoad) {
|
||||
options.onLoad(this);
|
||||
}
|
||||
|
||||
this.loadKeys().then(() => {
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
});
|
||||
},
|
||||
async loadKeys() {
|
||||
await this.generateSecurityNumber();
|
||||
this.render();
|
||||
},
|
||||
makeQRCode() {
|
||||
// Per Lilia: We can't turn this on until it generates a Latin1 string, as is
|
||||
// required by the mobile clients.
|
||||
new QRCode(this.$('.qr')[0]).makeCode(
|
||||
dcodeIO.ByteBuffer.wrap(this.ourKey).toString('base64')
|
||||
);
|
||||
},
|
||||
loadTheirKey() {
|
||||
const item = textsecure.storage.protocol.getIdentityRecord(
|
||||
this.model.get('id')
|
||||
);
|
||||
this.theirKey = item ? item.publicKey : null;
|
||||
},
|
||||
loadOurKey() {
|
||||
const item = textsecure.storage.protocol.getIdentityRecord(
|
||||
this.ourUuid || this.ourNumber
|
||||
);
|
||||
this.ourKey = item ? item.publicKey : null;
|
||||
},
|
||||
generateSecurityNumber() {
|
||||
return new libsignal.FingerprintGenerator(5200)
|
||||
.createFor(
|
||||
// TODO: we cannot use UUIDs for safety numbers yet
|
||||
// this.ourUuid || this.ourNumber,
|
||||
this.ourNumber,
|
||||
this.ourKey,
|
||||
// TODO: we cannot use UUIDs for safety numbers yet
|
||||
// this.model.get('uuid') || this.model.get('e164'),
|
||||
this.model.get('e164'),
|
||||
this.theirKey
|
||||
)
|
||||
.then(securityNumber => {
|
||||
this.securityNumber = securityNumber;
|
||||
});
|
||||
},
|
||||
onSafetyNumberChanged() {
|
||||
this.model.getProfiles().then(this.loadKeys.bind(this));
|
||||
|
||||
const dialog = new Whisper.ConfirmationDialogView({
|
||||
message: i18n('changedRightAfterVerify', [
|
||||
this.model.getTitle(),
|
||||
this.model.getTitle(),
|
||||
]),
|
||||
hideCancel: true,
|
||||
const view = new Whisper.ReactWrapperView({
|
||||
JSX: Signal.State.Roots.createSafetyNumberViewer(window.reduxStore, {
|
||||
contactID: options.model.get('id'),
|
||||
}),
|
||||
});
|
||||
|
||||
dialog.$el.insertBefore(this.el);
|
||||
dialog.focusCancel();
|
||||
},
|
||||
toggleVerified() {
|
||||
this.$('button.verify').attr('disabled', true);
|
||||
this.model
|
||||
.toggleVerified()
|
||||
.catch(result => {
|
||||
if (result instanceof Error) {
|
||||
if (result.name === 'OutgoingIdentityKeyError') {
|
||||
this.onSafetyNumberChanged();
|
||||
} else {
|
||||
window.log.error(
|
||||
'failed to toggle verified:',
|
||||
result && result.stack ? result.stack : result
|
||||
);
|
||||
}
|
||||
} else {
|
||||
const keyError = _.some(
|
||||
result.errors,
|
||||
error => error.name === 'OutgoingIdentityKeyError'
|
||||
);
|
||||
if (keyError) {
|
||||
this.onSafetyNumberChanged();
|
||||
} else {
|
||||
_.forEach(result.errors, error => {
|
||||
window.log.error(
|
||||
'failed to toggle verified:',
|
||||
error && error.stack ? error.stack : error
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
this.$('button.verify').removeAttr('disabled');
|
||||
});
|
||||
},
|
||||
render_attributes() {
|
||||
const s = this.securityNumber;
|
||||
const chunks = [];
|
||||
if (s) {
|
||||
for (let i = 0; i < s.length; i += 5) {
|
||||
chunks.push(s.substring(i, i + 5));
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < 12; i += 1) {
|
||||
chunks.push('XXXXX');
|
||||
}
|
||||
}
|
||||
const name = this.model.getTitle();
|
||||
const yourSafetyNumberWith = i18n(
|
||||
'yourSafetyNumberWith',
|
||||
this.model.getTitle()
|
||||
);
|
||||
const isVerified = this.model.isVerified();
|
||||
const verifyButton = isVerified ? i18n('unverify') : i18n('verify');
|
||||
const verifiedStatus = isVerified
|
||||
? i18n('isVerified', name)
|
||||
: i18n('isNotVerified', name);
|
||||
|
||||
return {
|
||||
learnMore: i18n('learnMore'),
|
||||
theirKeyUnknown: i18n('theirIdentityUnknown'),
|
||||
yourSafetyNumberWith,
|
||||
verifyHelp: i18n('verifyHelp', this.model.getTitle()),
|
||||
verifyButton,
|
||||
hasTheirKey: this.theirKey !== undefined,
|
||||
chunks,
|
||||
isVerified,
|
||||
verifiedStatus,
|
||||
};
|
||||
this.$('.key-verification-wrapper').append(view.el);
|
||||
},
|
||||
});
|
||||
})();
|
||||
|
|
39
js/views/safety_number_change_dialog_view.js
Normal file
39
js/views/safety_number_change_dialog_view.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
/* global Whisper, Signal */
|
||||
|
||||
// eslint-disable-next-line func-names
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
window.Whisper = window.Whisper || {};
|
||||
|
||||
Whisper.SafetyNumberChangeDialogView = Whisper.View.extend({
|
||||
templateName: 'safety-number-change-dialog',
|
||||
initialize(options) {
|
||||
const dialog = new Whisper.ReactWrapperView({
|
||||
Component: window.Signal.Components.SafetyNumberChangeDialog,
|
||||
props: {
|
||||
contacts: options.contacts.map(contact => contact.cachedProps),
|
||||
i18n: window.i18n,
|
||||
onCancel: () => {
|
||||
dialog.remove();
|
||||
this.remove();
|
||||
options.reject();
|
||||
},
|
||||
onConfirm: () => {
|
||||
dialog.remove();
|
||||
this.remove();
|
||||
options.resolve();
|
||||
},
|
||||
renderSafetyNumber(props) {
|
||||
return Signal.State.Roots.createSafetyNumberViewer(
|
||||
window.reduxStore,
|
||||
props
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
this.$('.safety-number-change-dialog-wrapper').append(dialog.el);
|
||||
},
|
||||
});
|
||||
})();
|
Loading…
Add table
Add a link
Reference in a new issue