From b769c1802155a8d6ed598f861a75b1cac52eba0b Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Sun, 17 Dec 2017 17:37:30 +0000 Subject: [PATCH] Show a shorter login form (only enc password) if already logged in. This is extremely useful for iOS devices where a PWA's session storage is deleted every time it's minimised, and it's also useful for people having multiple tabs open. --- src/LoginGate.tsx | 21 +++++- src/SideMenu/index.tsx | 2 +- src/components/EncryptionLoginForm.tsx | 97 ++++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 src/components/EncryptionLoginForm.tsx diff --git a/src/LoginGate.tsx b/src/LoginGate.tsx index 8eb7671..06e1fc5 100644 --- a/src/LoginGate.tsx +++ b/src/LoginGate.tsx @@ -4,9 +4,10 @@ import Container from './widgets/Container'; import ExternalLink from './widgets/ExternalLink'; import SyncGate from './SyncGate'; import LoginForm from './components/LoginForm'; +import EncryptionLoginForm from './components/EncryptionLoginForm'; import { store, CredentialsType } from './store'; -import { fetchCredentials } from './store/actions'; +import { fetchCredentials, deriveKey } from './store/actions'; import * as C from './constants'; @@ -18,6 +19,7 @@ class LoginGate extends React.Component { constructor(props: any) { super(props); this.onFormSubmit = this.onFormSubmit.bind(this); + this.onEncryptionFormSubmit = this.onEncryptionFormSubmit.bind(this); } onFormSubmit(username: string, password: string, encryptionPassword: string, serviceApiUrl?: string) { @@ -25,6 +27,10 @@ class LoginGate extends React.Component { store.dispatch(fetchCredentials(username, password, encryptionPassword, serviceApiUrl)); } + onEncryptionFormSubmit(encryptionPassword: string) { + store.dispatch(deriveKey(this.props.credentials.value!.credentials.email, encryptionPassword)); + } + render() { if (this.props.credentials.value === null) { const style = { @@ -55,6 +61,19 @@ class LoginGate extends React.Component { ); + } else if (this.props.credentials.value.encryptionKey === null) { + return ( + +

Encryption Password

+

+ You are logged in as {this.props.credentials.value.credentials.email}. + Please enter your encryption password to continue, or log out from the side menu. +

+ +
+ ); } return ( diff --git a/src/SideMenu/index.tsx b/src/SideMenu/index.tsx index d1bc550..ce23c7f 100644 --- a/src/SideMenu/index.tsx +++ b/src/SideMenu/index.tsx @@ -57,7 +57,7 @@ class SideMenu extends React.PureComponent { let loggedInItems; if (this.props.etesync) { - const journals = (this.props.journals && this.props.journals.value) && ( + const journals = (this.props.etesync.encryptionKey && this.props.journals && this.props.journals.value) && ( Journals diff --git a/src/components/EncryptionLoginForm.tsx b/src/components/EncryptionLoginForm.tsx new file mode 100644 index 0000000..38256ce --- /dev/null +++ b/src/components/EncryptionLoginForm.tsx @@ -0,0 +1,97 @@ +import * as React from 'react'; +import RaisedButton from 'material-ui/RaisedButton'; +import TextField from 'material-ui/TextField'; + +interface FormErrors { + errorEncryptionPassword?: string; +} + +class EncryptionLoginForm extends React.PureComponent { + state: { + errors: FormErrors, + encryptionPassword: string; + }; + + props: { + onSubmit: (encryptionPassword: string) => void; + loading?: boolean; + error?: Error; + }; + + constructor(props: any) { + super(props); + this.state = { + errors: {}, + encryptionPassword: '', + }; + this.generateEncryption = this.generateEncryption.bind(this); + this.handleInputChange = this.handleInputChange.bind(this); + } + + handleInputChange(event: React.ChangeEvent) { + const name = event.target.name; + const value = event.target.value; + this.setState({ + [name]: value + }); + } + + generateEncryption(e: any) { + e.preventDefault(); + + const encryptionPassword = this.state.encryptionPassword; + + let errors: FormErrors = {}; + const fieldRequired = 'This field is required!'; + if (!encryptionPassword) { + errors.errorEncryptionPassword = fieldRequired; + } + + if (Object.keys(errors).length) { + this.setState({errors: errors}); + return; + } else { + this.setState({errors: {}}); + } + + this.props.onSubmit(encryptionPassword); + } + + render() { + const styles = { + form: { + }, + submit: { + marginTop: 40, + textAlign: 'right', + }, + }; + + return ( + + {(this.props.error) && (
Error! {this.props.error.message}
)} +
+ + +
+ +
+ +
+ ); + } +} + +export default EncryptionLoginForm;