|
|
@ -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} />
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|