mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-17 14:05:04 +08:00
Alterations to DeviceVerifyDialog to support picking QR code
This commit is contained in:
parent
6b85ca2fb9
commit
5866d67c88
@ -27,16 +27,19 @@ import {verificationMethods} from 'matrix-js-sdk/src/crypto';
|
||||
import {ensureDMExists} from "../../../createRoom";
|
||||
import dis from "../../../dispatcher";
|
||||
import SettingsStore from '../../../settings/SettingsStore';
|
||||
import {SHOW_QR_CODE_METHOD} from "matrix-js-sdk/src/crypto/verification/QRCode";
|
||||
import VerificationQREmojiOptions from "../verification/VerificationQREmojiOptions";
|
||||
|
||||
const MODE_LEGACY = 'legacy';
|
||||
const MODE_SAS = 'sas';
|
||||
|
||||
const PHASE_START = 0;
|
||||
const PHASE_WAIT_FOR_PARTNER_TO_ACCEPT = 1;
|
||||
const PHASE_SHOW_SAS = 2;
|
||||
const PHASE_WAIT_FOR_PARTNER_TO_CONFIRM = 3;
|
||||
const PHASE_VERIFIED = 4;
|
||||
const PHASE_CANCELLED = 5;
|
||||
const PHASE_PICK_VERIFICATION_OPTION = 2;
|
||||
const PHASE_SHOW_SAS = 3;
|
||||
const PHASE_WAIT_FOR_PARTNER_TO_CONFIRM = 4;
|
||||
const PHASE_VERIFIED = 5;
|
||||
const PHASE_CANCELLED = 6;
|
||||
|
||||
export default class DeviceVerifyDialog extends React.Component {
|
||||
static propTypes = {
|
||||
@ -49,6 +52,7 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||
super();
|
||||
this._verifier = null;
|
||||
this._showSasEvent = null;
|
||||
this._request = null;
|
||||
this.state = {
|
||||
phase: PHASE_START,
|
||||
mode: MODE_SAS,
|
||||
@ -80,6 +84,25 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||
this.props.onFinished(false);
|
||||
}
|
||||
|
||||
_onUseSasClick = async () => {
|
||||
try {
|
||||
this._verifier = this._request.beginKeyVerification(verificationMethods.SAS);
|
||||
this._verifier.on('show_sas', this._onVerifierShowSas);
|
||||
// throws upon cancellation
|
||||
await this._verifier.verify();
|
||||
this.setState({phase: PHASE_VERIFIED});
|
||||
this._verifier.removeListener('show_sas', this._onVerifierShowSas);
|
||||
this._verifier = null;
|
||||
} catch (e) {
|
||||
console.log("Verification failed", e);
|
||||
this.setState({
|
||||
phase: PHASE_CANCELLED,
|
||||
});
|
||||
this._verifier = null;
|
||||
this._request = null;
|
||||
}
|
||||
};
|
||||
|
||||
_onLegacyFinished = (confirm) => {
|
||||
if (confirm) {
|
||||
MatrixClientPeg.get().setDeviceVerified(
|
||||
@ -108,11 +131,20 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||
} else {
|
||||
this._verifier = request.verifier;
|
||||
}
|
||||
} else if (verifyingOwnDevice && SettingsStore.isFeatureEnabled("feature_cross_signing")) {
|
||||
this._request = await client.requestVerification(this.props.userId,[
|
||||
verificationMethods.SAS,
|
||||
SHOW_QR_CODE_METHOD,
|
||||
]);
|
||||
|
||||
await this._request.waitFor(r => r.ready || r.started);
|
||||
this.setState({phase: PHASE_PICK_VERIFICATION_OPTION});
|
||||
} else {
|
||||
this._verifier = client.beginKeyVerification(
|
||||
verificationMethods.SAS, this.props.userId, this.props.device.deviceId,
|
||||
);
|
||||
}
|
||||
if (!this._verifier) return;
|
||||
this._verifier.on('show_sas', this._onVerifierShowSas);
|
||||
// throws upon cancellation
|
||||
await this._verifier.verify();
|
||||
@ -150,10 +182,13 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||
let body;
|
||||
switch (this.state.phase) {
|
||||
case PHASE_START:
|
||||
body = this._renderSasVerificationPhaseStart();
|
||||
body = this._renderVerificationPhaseStart();
|
||||
break;
|
||||
case PHASE_WAIT_FOR_PARTNER_TO_ACCEPT:
|
||||
body = this._renderSasVerificationPhaseWaitAccept();
|
||||
body = this._renderVerificationPhaseWaitAccept();
|
||||
break;
|
||||
case PHASE_PICK_VERIFICATION_OPTION:
|
||||
body = this._renderVerificationPhasePick();
|
||||
break;
|
||||
case PHASE_SHOW_SAS:
|
||||
body = this._renderSasVerificationPhaseShowSas();
|
||||
@ -162,10 +197,10 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||
body = this._renderSasVerificationPhaseWaitForPartnerToConfirm();
|
||||
break;
|
||||
case PHASE_VERIFIED:
|
||||
body = this._renderSasVerificationPhaseVerified();
|
||||
body = this._renderVerificationPhaseVerified();
|
||||
break;
|
||||
case PHASE_CANCELLED:
|
||||
body = this._renderSasVerificationPhaseCancelled();
|
||||
body = this._renderVerificationPhaseCancelled();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -180,7 +215,7 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
_renderSasVerificationPhaseStart() {
|
||||
_renderVerificationPhaseStart() {
|
||||
const AccessibleButton = sdk.getComponent('views.elements.AccessibleButton');
|
||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||
return (
|
||||
@ -206,7 +241,7 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
_renderSasVerificationPhaseWaitAccept() {
|
||||
_renderVerificationPhaseWaitAccept() {
|
||||
const Spinner = sdk.getComponent("views.elements.Spinner");
|
||||
const AccessibleButton = sdk.getComponent('views.elements.AccessibleButton');
|
||||
|
||||
@ -227,6 +262,14 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
_renderVerificationPhasePick() {
|
||||
return <VerificationQREmojiOptions
|
||||
request={this._request}
|
||||
onCancel={this._onCancelClick}
|
||||
onStartEmoji={this._onUseSasClick}
|
||||
/>;
|
||||
}
|
||||
|
||||
_renderSasVerificationPhaseShowSas() {
|
||||
const VerificationShowSas = sdk.getComponent('views.verification.VerificationShowSas');
|
||||
return <VerificationShowSas
|
||||
@ -234,6 +277,7 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||
onCancel={this._onCancelClick}
|
||||
onDone={this._onSasMatchesClick}
|
||||
isSelf={MatrixClientPeg.get().getUserId() === this.props.userId}
|
||||
onStartEmoji={this._onUseSasClick}
|
||||
/>;
|
||||
}
|
||||
|
||||
@ -247,12 +291,12 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||
</div>;
|
||||
}
|
||||
|
||||
_renderSasVerificationPhaseVerified() {
|
||||
_renderVerificationPhaseVerified() {
|
||||
const VerificationComplete = sdk.getComponent('views.verification.VerificationComplete');
|
||||
return <VerificationComplete onDone={this._onVerifiedDoneClick} />;
|
||||
}
|
||||
|
||||
_renderSasVerificationPhaseCancelled() {
|
||||
_renderVerificationPhaseCancelled() {
|
||||
const VerificationCancelled = sdk.getComponent('views.verification.VerificationCancelled');
|
||||
return <VerificationCancelled onDone={this._onCancelClick} />;
|
||||
}
|
||||
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { _t, _td } from '../../../languageHandler';
|
||||
import {PendingActionSpinner} from "../right_panel/EncryptionInfo";
|
||||
import AccessibleButton from "../elements/AccessibleButton";
|
||||
import DialogButtons from "../elements/DialogButtons";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import VerificationQRCode from "../elements/crypto/VerificationQRCode";
|
||||
import {VerificationRequest} from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
|
||||
import Spinner from "../elements/Spinner";
|
||||
|
||||
@replaceableComponent("views.verification.VerificationQREmojiOptions")
|
||||
export default class VerificationQREmojiOptions extends React.Component {
|
||||
static propTypes = {
|
||||
request: PropTypes.object.isRequired,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
onStartEmoji: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
qrProps: null,
|
||||
};
|
||||
|
||||
this._prepareQrCode(props.request);
|
||||
}
|
||||
|
||||
async _prepareQrCode(request: VerificationRequest) {
|
||||
try {
|
||||
const props = await VerificationQRCode.getPropsForRequest(request);
|
||||
this.setState({qrProps: props});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
// We just won't show a QR code
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let qrCode = <div className='mx_VerificationQREmojiOptions_noQR'><Spinner /></div>;
|
||||
if (this.state.qrProps) {
|
||||
qrCode = <VerificationQRCode {...this.state.qrProps} />;
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
{_t("Verify this session by completing one of the following:")}
|
||||
<div className='mx_IncomingSasDialog_startOptions'>
|
||||
<div className='mx_IncomingSasDialog_startOption'>
|
||||
<p>{_t("Scan this unique code")}</p>
|
||||
{qrCode}
|
||||
</div>
|
||||
<span>{_t("or")}</span>
|
||||
<div className='mx_IncomingSasDialog_startOption'>
|
||||
<p>{_t("Compare unique emoji")}</p>
|
||||
<span>{_t("Compare a unique set of emoji if you don't have a camera on either device")}</span>
|
||||
<AccessibleButton onClick={this.props.onStartEmoji} kind='primary'>
|
||||
{_t("Start")}
|
||||
</AccessibleButton>
|
||||
</div>
|
||||
</div>
|
||||
<AccessibleButton onClick={this.props.onCancel} kind='danger'>
|
||||
{_t("Cancel")}
|
||||
</AccessibleButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -451,6 +451,12 @@
|
||||
"You've successfully verified this user.": "You've successfully verified this user.",
|
||||
"Secure messages with this user are end-to-end encrypted and not able to be read by third parties.": "Secure messages with this user are end-to-end encrypted and not able to be read by third parties.",
|
||||
"Got It": "Got It",
|
||||
"Verify this session by completing one of the following:": "Verify this session by completing one of the following:",
|
||||
"Scan this unique code": "Scan this unique code",
|
||||
"or": "or",
|
||||
"Compare unique emoji": "Compare unique emoji",
|
||||
"Compare a unique set of emoji if you don't have a camera on either device": "Compare a unique set of emoji if you don't have a camera on either device",
|
||||
"Start": "Start",
|
||||
"Confirm the emoji below are displayed on both devices, in the same order:": "Confirm the emoji below are displayed on both devices, in the same order:",
|
||||
"Verify this user by confirming the following emoji appear on their screen.": "Verify this user by confirming the following emoji appear on their screen.",
|
||||
"Verify this device by confirming the following number appears on its screen.": "Verify this device by confirming the following number appears on its screen.",
|
||||
@ -1924,7 +1930,6 @@
|
||||
"Could not load user profile": "Could not load user profile",
|
||||
"Complete security": "Complete security",
|
||||
"Verify this session to grant it access to encrypted messages.": "Verify this session to grant it access to encrypted messages.",
|
||||
"Start": "Start",
|
||||
"Session verified": "Session verified",
|
||||
"Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.",
|
||||
"Your new session is now verified. Other users will see it as trusted.": "Your new session is now verified. Other users will see it as trusted.",
|
||||
|
Loading…
Reference in New Issue
Block a user