Add SecretStorageAccess component
Signed-off-by: Ajay Bura <ajbura@gmail.com>
This commit is contained in:
parent
ebd581d173
commit
d0cec1108a
2 changed files with 112 additions and 0 deletions
92
src/app/organisms/settings/SecretStorageAccess.jsx
Normal file
92
src/app/organisms/settings/SecretStorageAccess.jsx
Normal file
|
@ -0,0 +1,92 @@
|
|||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import './SecretStorageAccess.scss';
|
||||
import { deriveKey } from 'matrix-js-sdk/lib/crypto/key_passphrase';
|
||||
|
||||
import initMatrix from '../../../client/initMatrix';
|
||||
|
||||
import Text from '../../atoms/text/Text';
|
||||
import Button from '../../atoms/button/Button';
|
||||
import Input from '../../atoms/input/Input';
|
||||
import Spinner from '../../atoms/spinner/Spinner';
|
||||
|
||||
import { useStore } from '../../hooks/useStore';
|
||||
|
||||
function SecretStorageAccess({ onComplete }) {
|
||||
const mx = initMatrix.matrixClient;
|
||||
const sSKeyId = mx.getAccountData('m.secret_storage.default_key').getContent().key;
|
||||
const sSKeyInfo = mx.getAccountData(`m.secret_storage.key.${sSKeyId}`).getContent();
|
||||
const isPassphrase = !!sSKeyInfo.passphrase;
|
||||
const [withPhrase, setWithPhrase] = useState(isPassphrase);
|
||||
const [process, setProcess] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
const mountStore = useStore();
|
||||
mountStore.setItem(true);
|
||||
|
||||
const toggleWithPhrase = () => setWithPhrase(!withPhrase);
|
||||
|
||||
const processInput = async ({ key, phrase }) => {
|
||||
setProcess(true);
|
||||
try {
|
||||
const { salt, iterations } = sSKeyInfo.passphrase;
|
||||
const decodedKey = key
|
||||
? mx.keyBackupKeyFromRecoveryKey(key)
|
||||
: await deriveKey(phrase, salt, iterations);
|
||||
const isCorrect = await mx.checkSecretStorageKey(decodedKey, sSKeyInfo);
|
||||
|
||||
if (!mountStore.getItem()) return;
|
||||
if (!isCorrect) {
|
||||
setError(`Incorrect Security ${key ? 'Key' : 'Phrase'}`);
|
||||
setProcess(false);
|
||||
return;
|
||||
}
|
||||
onComplete({ key, phrase, decodedKey });
|
||||
} catch (e) {
|
||||
if (!mountStore.getItem()) return;
|
||||
setError(`Incorrect Security ${key ? 'Key' : 'Phrase'}`);
|
||||
setProcess(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleForm = async (e) => {
|
||||
e.preventDefault();
|
||||
const password = e.target.password.value;
|
||||
if (password.trim() === '') return;
|
||||
const data = {};
|
||||
if (withPhrase) data.phrase = password;
|
||||
else data.key = password;
|
||||
processInput(data);
|
||||
};
|
||||
|
||||
const handleChange = () => {
|
||||
setError(null);
|
||||
setProcess(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="secret-storage-access">
|
||||
<form onSubmit={handleForm}>
|
||||
<Input
|
||||
name="password"
|
||||
label={`Security ${withPhrase ? 'Phrase' : 'Key'}`}
|
||||
type="password"
|
||||
onChange={handleChange}
|
||||
required
|
||||
/>
|
||||
{error && <Text variant="b3">{error}</Text>}
|
||||
{!process && (
|
||||
<div className="secret-storage-access__btn">
|
||||
<Button variant="primary" type="submit">Continue</Button>
|
||||
{isPassphrase && <Button onClick={toggleWithPhrase}>{`Use Security ${withPhrase ? 'Key' : 'Phrase'}`}</Button>}
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
{process && <Spinner size="small" />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
SecretStorageAccess.propTypes = {
|
||||
onComplete: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default SecretStorageAccess;
|
20
src/app/organisms/settings/SecretStorageAccess.scss
Normal file
20
src/app/organisms/settings/SecretStorageAccess.scss
Normal file
|
@ -0,0 +1,20 @@
|
|||
.secret-storage-access {
|
||||
padding: var(--sp-normal);
|
||||
|
||||
& form > *:not(:first-child) {
|
||||
margin-top: var(--sp-normal);
|
||||
}
|
||||
|
||||
& .text-b3 {
|
||||
color: var(--tc-danger-high);
|
||||
margin-top: var(--sp-ultra-tight) !important;
|
||||
}
|
||||
|
||||
&__btn {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
& .donut-spinner {
|
||||
margin-top: var(--sp-normal);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue