mirror of
				https://github.com/vector-im/element-web.git
				synced 2025-11-04 02:02:14 +01: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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user