Skip to content

Commit

Permalink
Update safety number change warning dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
josh-signal authored and scottnonnenberg-signal committed Jul 30, 2020
1 parent e87a010 commit 5b83485
Show file tree
Hide file tree
Showing 38 changed files with 1,221 additions and 425 deletions.
22 changes: 22 additions & 0 deletions .storybook/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,28 @@ addDecorator((storyFn /* , context */) => {
const secondPaneDeviceTheme = makeDeviceThemeKnob('Second');
const secondPaneMode = makeModeKnob('Second');

// Adding it to the body as well so that we can cover modals and other
// components that are rendered outside of this decorator container
if (firstPaneTheme === '') {
document.body.classList.remove('dark-theme');
} else {
document.body.classList.add('dark-theme');
}

if (firstPaneDeviceTheme === '') {
document.body.classList.remove('ios-theme');
} else {
document.body.classList.add('ios-theme');
}

if (firstPaneMode === 'mouse-mode') {
document.body.classList.remove('keyboard-mode');
document.body.classList.add('mouse-mode');
} else {
document.body.classList.remove('mouse-mode');
document.body.classList.add('keyboard-mode');
}

return (
<div className={styles.container}>
<ClassyProvider themes={['dark']}>
Expand Down
32 changes: 6 additions & 26 deletions _locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -345,20 +345,6 @@
"message": "Your safety numbers with these group members have changed since you last verified. Click a group member to see your new safety number with them.",
"description": "When there are multiple previously-verified group members with safety number changes, a banner will be shown. The list of contacts with safety number changes is shown, and this text introduces that list."
},
"changedSinceVerifiedMultiple": {
"message": "Your safety numbers with multiple group members have changed since you last verified. This could mean that someone is trying to intercept your communication or that they have simply reinstalled Signal.",
"description": "Shown on confirmation dialog when user attempts to send a message"
},
"changedSinceVerified": {
"message": "Your safety number with $name$ has changed since you last verified. This could mean that someone is trying to intercept your communication or that $name$ has simply reinstalled Signal.",
"description": "Shown on confirmation dialog when user attempts to send a message",
"placeholders": {
"name": {
"content": "$1",
"example": "Bob"
}
}
},
"changedRightAfterVerify": {
"message": "The safety number you are trying to verify has changed. Please review your new safety number with $name$. Remember, this change could mean that someone is trying to intercept your communication or that $name$ has simply reinstalled Signal.",
"description": "Shown on the safety number screen when the user has selected to verify/unverify a contact's safety number, and we immediately discover a safety number change",
Expand All @@ -369,20 +355,10 @@
}
}
},
"changedRecentlyMultiple": {
"message": "Your safety numbers with multiple group members have changed recently. This could mean that someone is trying to intercept your communication or that they have simply reinstalled Signal.",
"changedVerificationWarning": {
"message": "The following people may have reinstalled or changed devices. Verify your safety number with them to ensure privacy.",
"description": "Shown on confirmation dialog when user attempts to send a message"
},
"changedRecently": {
"message": "Your safety number with $name$ has changed recently. This could mean that someone is trying to intercept your communication or that $name$ has simply reinstalled Signal.",
"description": "Shown on confirmation dialog when user attempts to send a message",
"placeholders": {
"name": {
"content": "$1",
"example": "Bob"
}
}
},
"identityKeyErrorOnSend": {
"message": "Your safety number with $name$ has changed. This could either mean that someone is trying to intercept your communication or that $name$ has simply reinstalled Signal. You may wish to verify your safety number with this contact.",
"description": "Shown when user clicks on a failed recipient in the message detail view after an identity key change",
Expand Down Expand Up @@ -1579,6 +1555,10 @@
"message": "Safety Number has changed",
"description": "A notification shown in the conversation when a contact reinstalls"
},
"safetyNumberChanges": {
"message": "Safety Number Changes",
"description": "Title for safety number changed modal"
},
"safetyNumberChangedGroup": {
"message": "Safety Number with $name$ has changed",
"description": "A notification shown in a group conversation when a contact reinstalls, showing the contact name",
Expand Down
34 changes: 7 additions & 27 deletions background.html
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ <h3>{{ welcomeToSignal }}</h3>
</div>
</script>

<script type='text/x-tmpl-mustache' id='safety-number-change-dialog'>
<div class='safety-number-change-dialog-wrapper'></div>
</script>

<script type='text/x-tmpl-mustache' id='identicon-svg'>
<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100'>
<circle cx='50' cy='50' r='40' fill='{{ color }}' />
Expand Down Expand Up @@ -156,33 +160,8 @@ <h3>{{ welcomeToSignal }}</h3>
</script>

<script type='text/x-tmpl-mustache' id='key-verification'>
<div class='container' tabindex='0'>
{{ ^hasTheirKey }}
<div class='placeholder'>{{ theirKeyUnknown }}</div>
{{ /hasTheirKey }}
{{ #hasTheirKey }}
<label> {{ yourSafetyNumberWith }} </label>
<!--<div class='qr'></div>-->
<div class='key'>
{{ #chunks }} <span>{{ . }}</span> {{ /chunks }}
</div>
{{ /hasTheirKey }}
{{ verifyHelp }}
<p> {{> link_to_support }} </p>
<div class='summary'>
{{ #isVerified }}
<span class='icon verified'></span>
{{ /isVerified }}
{{ ^isVerified }}
<span class='icon shield'></span>
{{ /isVerified }}
{{ verifiedStatus }}
</div>
<div class='verify'>
<button class='verify grey'>
{{ verifyButton }}
</button>
</div>
<div class="container" tabindex="0">
<div class="key-verification-wrapper"></div>
</div>
</script>

Expand Down Expand Up @@ -387,6 +366,7 @@ <h3>{{ welcomeToSignal }}</h3>
<script type='text/javascript' src='js/views/install_view.js'></script>
<script type='text/javascript' src='js/views/banner_view.js'></script>
<script type="text/javascript" src="js/views/phone-input-view.js"></script>
<script type='text/javascript' src='js/views/safety_number_change_dialog_view.js'></script>
<script type='text/javascript' src='js/views/standalone_registration_view.js'></script>
<script type='text/javascript' src='js/views/app_view.js'></script>
<script type='text/javascript' src='js/views/clear_data_view.js'></script>
Expand Down
3 changes: 3 additions & 0 deletions js/models/conversations.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 8 additions & 0 deletions js/modules/signal.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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');
Expand Down Expand Up @@ -274,6 +280,7 @@ exports.setup = (options = {}) => {
MediaGallery,
MessageDetail,
Quote,
SafetyNumberChangeDialog,
StagedLinkPreview,
Types: {
Message: MediaGalleryMessage,
Expand All @@ -284,6 +291,7 @@ exports.setup = (options = {}) => {
createCallManager,
createCompositionArea,
createLeftPane,
createSafetyNumberViewer,
createShortcutGuideModal,
createStickerManager,
createStickerPreviewModal,
Expand Down
32 changes: 8 additions & 24 deletions js/views/conversation_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
},

Expand Down
148 changes: 7 additions & 141 deletions js/views/key_verification_view.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* global Whisper, textsecure, QRCode, dcodeIO, libsignal, i18n, _ */
/* global Whisper, Signal */

/* eslint-disable more/no-then */

Expand All @@ -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);
const view = new Whisper.ReactWrapperView({
JSX: Signal.State.Roots.createSafetyNumberViewer(window.reduxStore, {
contactID: options.model.get('id'),
}),
});
},
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,
});

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);
},
});
})();
Loading

0 comments on commit 5b83485

Please sign in to comment.