-
-
Notifications
You must be signed in to change notification settings - Fork 252
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Session verification by emojis (#513)
* Add option to verify with security key/phrase * Manually merge #311 by @ginnyTheCat
- Loading branch information
Showing
9 changed files
with
270 additions
and
12 deletions.
There are no files selected for viewing
153 changes: 153 additions & 0 deletions
153
src/app/organisms/emoji-verification/EmojiVerification.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
/* eslint-disable react/prop-types */ | ||
import React, { useState, useEffect } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import './EmojiVerification.scss'; | ||
import { twemojify } from '../../../util/twemojify'; | ||
|
||
import initMatrix from '../../../client/initMatrix'; | ||
import cons from '../../../client/state/cons'; | ||
import navigation from '../../../client/state/navigation'; | ||
|
||
import Text from '../../atoms/text/Text'; | ||
import IconButton from '../../atoms/button/IconButton'; | ||
import Button from '../../atoms/button/Button'; | ||
import Spinner from '../../atoms/spinner/Spinner'; | ||
import Dialog from '../../molecules/dialog/Dialog'; | ||
|
||
import CrossIC from '../../../../public/res/ic/outlined/cross.svg'; | ||
import { useStore } from '../../hooks/useStore'; | ||
|
||
function EmojiVerificationContent({ request, requestClose }) { | ||
const [sas, setSas] = useState(null); | ||
const [process, setProcess] = useState(false); | ||
const mountStore = useStore(); | ||
mountStore.setItem(true); | ||
|
||
const handleChange = () => { | ||
if (request.done || request.cancelled) requestClose(); | ||
}; | ||
|
||
useEffect(() => { | ||
mountStore.setItem(true); | ||
if (request === null) return null; | ||
const req = request; | ||
req.on('change', handleChange); | ||
return () => req.off('change', handleChange); | ||
}, [request]); | ||
|
||
const acceptRequest = async () => { | ||
setProcess(true); | ||
await request.accept(); | ||
|
||
const verifier = request.beginKeyVerification('m.sas.v1'); | ||
verifier.on('show_sas', (data) => { | ||
if (!mountStore.getItem()) return; | ||
setSas(data); | ||
setProcess(false); | ||
}); | ||
await verifier.verify(); | ||
}; | ||
|
||
const sasMismatch = () => { | ||
sas.mismatch(); | ||
setProcess(true); | ||
}; | ||
|
||
const sasConfirm = () => { | ||
sas.confirm(); | ||
setProcess(true); | ||
}; | ||
|
||
const renderWait = () => ( | ||
<> | ||
<Spinner size="small" /> | ||
<Text>Waiting for response from other device...</Text> | ||
</> | ||
); | ||
|
||
if (sas !== null) { | ||
return ( | ||
<div className="emoji-verification__content"> | ||
<Text>Confirm the emoji below are displayed on both devices, in the same order:</Text> | ||
<div className="emoji-verification__emojis"> | ||
{sas.sas.emoji.map((emoji) => ( | ||
<div className="emoji-verification__emoji-block" key={emoji[1]}> | ||
<Text variant="h1">{twemojify(emoji[0])}</Text> | ||
<Text>{emoji[1]}</Text> | ||
</div> | ||
))} | ||
</div> | ||
<div className="emoji-verification__buttons"> | ||
{process ? renderWait() : ( | ||
<> | ||
<Button variant="primary" onClick={sasConfirm}>They match</Button> | ||
<Button onClick={sasMismatch}>{'They don\'t match'}</Button> | ||
</> | ||
)} | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
return ( | ||
<div className="emoji-verification__content"> | ||
<Text>Click accept to start the verification process</Text> | ||
<div className="emoji-verification__buttons"> | ||
{ | ||
process | ||
? renderWait() | ||
: <Button variant="primary" onClick={acceptRequest}>Accept</Button> | ||
} | ||
</div> | ||
</div> | ||
); | ||
} | ||
EmojiVerificationContent.propTypes = { | ||
request: PropTypes.shape({}).isRequired, | ||
requestClose: PropTypes.func.isRequired, | ||
}; | ||
|
||
function useVisibilityToggle() { | ||
const [request, setRequest] = useState(null); | ||
const mx = initMatrix.matrixClient; | ||
|
||
useEffect(() => { | ||
const handleOpen = (req) => setRequest(req); | ||
navigation.on(cons.events.navigation.EMOJI_VERIFICATION_OPENED, handleOpen); | ||
mx.on('crypto.verification.request', handleOpen); | ||
return () => { | ||
navigation.removeListener(cons.events.navigation.EMOJI_VERIFICATION_OPENED, handleOpen); | ||
mx.removeListener('crypto.verification.request', handleOpen); | ||
}; | ||
}, []); | ||
|
||
const requestClose = () => setRequest(null); | ||
|
||
return [request, requestClose]; | ||
} | ||
|
||
function EmojiVerification() { | ||
const [request, requestClose] = useVisibilityToggle(); | ||
|
||
return ( | ||
<Dialog | ||
isOpen={request !== null} | ||
className="emoji-verification" | ||
title={( | ||
<Text variant="s1" weight="medium" primary> | ||
Emoji verification | ||
</Text> | ||
)} | ||
contentOptions={<IconButton src={CrossIC} onClick={requestClose} tooltip="Close" />} | ||
onRequestClose={requestClose} | ||
> | ||
{ | ||
request !== null | ||
? <EmojiVerificationContent request={request} requestClose={requestClose} /> | ||
: <div /> | ||
} | ||
</Dialog> | ||
); | ||
} | ||
|
||
export default EmojiVerification; |
35 changes: 35 additions & 0 deletions
35
src/app/organisms/emoji-verification/EmojiVerification.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
@use '../../partials/flex'; | ||
@use '../../partials/dir'; | ||
|
||
.emoji-verification { | ||
&__content { | ||
padding: var(--sp-normal); | ||
@include dir.side(padding, var(--sp-normal), var(--sp-extra-tight)); | ||
display: flex; | ||
flex-direction: column; | ||
gap: var(--sp-normal); | ||
} | ||
|
||
&__emojis { | ||
margin: var(--sp-loose) 0; | ||
display: flex; | ||
align-items: center; | ||
justify-content: space-around; | ||
gap: var(--sp-extra-tight); | ||
flex-wrap: wrap; | ||
} | ||
|
||
&__emoji-block { | ||
@extend .cp-fx__column; | ||
flex: 1; | ||
align-items: center; | ||
gap: var(--sp-extra-tight); | ||
white-space: nowrap; | ||
text-transform: capitalize; | ||
} | ||
|
||
&__buttons { | ||
display: flex; | ||
gap: var(--sp-normal); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.