Login screen: gracefully handle wrong encryption passwords.

master
Tom Hacohen 5 years ago
parent eb124ed604
commit fc4b3294f1

@ -1,5 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import { Action } from 'redux-actions';
import Container from './widgets/Container'; import Container from './widgets/Container';
import ExternalLink from './widgets/ExternalLink'; import ExternalLink from './widgets/ExternalLink';
import SyncGate from './SyncGate'; import SyncGate from './SyncGate';
@ -9,22 +11,24 @@ import EncryptionLoginForm from './components/EncryptionLoginForm';
import { store, CredentialsType } from './store'; import { store, CredentialsType } from './store';
import { deriveKey, fetchCredentials, fetchUserInfo } from './store/actions'; import { deriveKey, fetchCredentials, fetchUserInfo } from './store/actions';
import * as EteSync from 'etesync';
import * as C from './constants'; import * as C from './constants';
import SignedPagesBadge from './images/signed-pages-badge.svg'; import SignedPagesBadge from './images/signed-pages-badge.svg';
import LoadingIndicator from './widgets/LoadingIndicator'; import LoadingIndicator from './widgets/LoadingIndicator';
function EncryptionPart(props: { credentials: CredentialsType, onEncryptionFormSubmit: (encryptionPassword: string) => void }) { function EncryptionPart(props: { credentials: CredentialsType }) {
const [fetched, setFetched] = React.useState(false); const [fetched, setFetched] = React.useState(false);
const [isNewUser, setIsNewUser] = React.useState(false); const [userInfo, setUserInfo] = React.useState<EteSync.UserInfo>();
const [error, setError] = React.useState<Error>();
const credentials = props.credentials.value!; const credentials = props.credentials.value!;
React.useEffect(() => { React.useEffect(() => {
// FIXME: verify the error is a 404 // FIXME: verify the error is a 404
store.dispatch<any>(fetchUserInfo(credentials, credentials.credentials.email)).catch(() => { store.dispatch<any>(fetchUserInfo(credentials, credentials.credentials.email)).then((fetchedUserInfo: Action<EteSync.UserInfo>) => {
setIsNewUser(true); setUserInfo(fetchedUserInfo.payload);
}).finally(() => { }).finally(() => {
setFetched(true); setFetched(true);
}); });
@ -34,6 +38,21 @@ function EncryptionPart(props: { credentials: CredentialsType, onEncryptionFormS
return <LoadingIndicator />; return <LoadingIndicator />;
} }
function onEncryptionFormSubmit(encryptionPassword: string) {
const derivedAction = deriveKey(props.credentials.value!.credentials.email, encryptionPassword);
if (userInfo) {
const userInfoCryptoManager = userInfo.getCryptoManager(derivedAction.payload!);
try {
userInfo.verify(userInfoCryptoManager);
} catch (e) {
setError(new EteSync.EncryptionPasswordError('Wrong encryption password'));
return;
}
}
store.dispatch(derivedAction);
}
const isNewUser = !userInfo;
return ( return (
<Container style={{ maxWidth: '30rem' }}> <Container style={{ maxWidth: '30rem' }}>
@ -53,7 +72,8 @@ function EncryptionPart(props: { credentials: CredentialsType, onEncryptionFormS
} }
<EncryptionLoginForm <EncryptionLoginForm
onSubmit={props.onEncryptionFormSubmit} error={error}
onSubmit={onEncryptionFormSubmit}
/> />
</Container> </Container>
); );
@ -68,7 +88,6 @@ class LoginGate extends React.Component {
constructor(props: any) { constructor(props: any) {
super(props); super(props);
this.onFormSubmit = this.onFormSubmit.bind(this); this.onFormSubmit = this.onFormSubmit.bind(this);
this.onEncryptionFormSubmit = this.onEncryptionFormSubmit.bind(this);
} }
public onFormSubmit(username: string, password: string, serviceApiUrl?: string) { public onFormSubmit(username: string, password: string, serviceApiUrl?: string) {
@ -76,10 +95,6 @@ class LoginGate extends React.Component {
store.dispatch<any>(fetchCredentials(username, password, serviceApiUrl)); store.dispatch<any>(fetchCredentials(username, password, serviceApiUrl));
} }
public onEncryptionFormSubmit(encryptionPassword: string) {
store.dispatch(deriveKey(this.props.credentials.value!.credentials.email, encryptionPassword));
}
public render() { public render() {
if (this.props.credentials.value === null) { if (this.props.credentials.value === null) {
const style = { const style = {
@ -118,7 +133,7 @@ class LoginGate extends React.Component {
); );
} else if (this.props.credentials.value.encryptionKey === null) { } else if (this.props.credentials.value.encryptionKey === null) {
return ( return (
<EncryptionPart credentials={this.props.credentials} onEncryptionFormSubmit={this.onEncryptionFormSubmit} /> <EncryptionPart credentials={this.props.credentials} />
); );
} }

Loading…
Cancel
Save