Meriadec Pillet
7 years ago
committed by
GitHub
21 changed files with 416 additions and 50 deletions
@ -0,0 +1,17 @@ |
|||
// @flow
|
|||
|
|||
import db from 'helpers/db' |
|||
|
|||
import type { Settings } from 'types/common' |
|||
|
|||
export type SaveSettings = Settings => { type: string, payload: Settings } |
|||
export const saveSettings: SaveSettings = payload => ({ |
|||
type: 'DB:SAVE_SETTINGS', |
|||
payload, |
|||
}) |
|||
|
|||
type FetchSettings = () => { type: string } |
|||
export const fetchSettings: FetchSettings = () => ({ |
|||
type: 'FETCH_SETTINGS', |
|||
payload: db('settings'), |
|||
}) |
@ -1,13 +1,36 @@ |
|||
// @flow
|
|||
|
|||
import React, { PureComponent } from 'react' |
|||
import { connect } from 'react-redux' |
|||
|
|||
import type { MapStateToProps } from 'react-redux' |
|||
import type { Account } from 'types/common' |
|||
|
|||
import { getAccountById } from 'reducers/accounts' |
|||
|
|||
import Box from 'components/base/Box' |
|||
|
|||
class AccountPage extends PureComponent<{}> { |
|||
type Props = { |
|||
account: Account, |
|||
} |
|||
|
|||
const mapStateToProps: MapStateToProps<*, *, *> = (state, props) => ({ |
|||
account: getAccountById(state, props.match.params.id), |
|||
}) |
|||
|
|||
class AccountPage extends PureComponent<Props> { |
|||
render() { |
|||
return <Box>{'account page'}</Box> |
|||
const { account } = this.props |
|||
|
|||
return ( |
|||
<Box> |
|||
<Box>{'account page'}</Box> |
|||
<Box> |
|||
{account.name} - {account.address} |
|||
</Box> |
|||
</Box> |
|||
) |
|||
} |
|||
} |
|||
|
|||
export default AccountPage |
|||
export default connect(mapStateToProps)(AccountPage) |
|||
|
@ -0,0 +1,100 @@ |
|||
// @flow
|
|||
|
|||
import React, { PureComponent } from 'react' |
|||
import { connect } from 'react-redux' |
|||
import bcrypt from 'bcryptjs' |
|||
|
|||
import type { MapStateToProps } from 'react-redux' |
|||
import type { Settings } from 'types/common' |
|||
|
|||
import get from 'lodash/get' |
|||
|
|||
import { setEncryptionKey } from 'helpers/db' |
|||
|
|||
import { fetchAccounts } from 'actions/accounts' |
|||
import { isLocked, unlock } from 'reducers/application' |
|||
|
|||
import Box from 'components/base/Box' |
|||
import Input from 'components/base/Input' |
|||
|
|||
type InputValue = { |
|||
password: string, |
|||
} |
|||
|
|||
type Props = { |
|||
fetchAccounts: Function, |
|||
isLocked: boolean, |
|||
render: Function, |
|||
settings: Settings, |
|||
unlock: Function, |
|||
} |
|||
type State = { |
|||
inputValue: InputValue, |
|||
} |
|||
|
|||
const mapStateToProps: MapStateToProps<*, *, *> = state => ({ |
|||
settings: state.settings, |
|||
isLocked: isLocked(state), |
|||
}) |
|||
|
|||
const mapDispatchToProps = { |
|||
fetchAccounts, |
|||
unlock, |
|||
} |
|||
|
|||
class IsUnlocked extends PureComponent<Props, State> { |
|||
state = { |
|||
inputValue: { |
|||
password: '', |
|||
}, |
|||
} |
|||
|
|||
handleChangeInput = (key: $Keys<InputValue>) => (value: $Values<InputValue>) => |
|||
this.setState(prev => ({ |
|||
inputValue: { |
|||
...prev.inputValue, |
|||
[key]: value, |
|||
}, |
|||
})) |
|||
|
|||
handleSubmit = (e: SyntheticEvent<HTMLFormElement>) => { |
|||
e.preventDefault() |
|||
|
|||
const { settings, unlock, fetchAccounts } = this.props |
|||
const { inputValue } = this.state |
|||
|
|||
if (bcrypt.compareSync(inputValue.password, get(settings, 'password.value'))) { |
|||
setEncryptionKey('accounts', inputValue.password) |
|||
fetchAccounts() |
|||
unlock() |
|||
} |
|||
} |
|||
|
|||
render() { |
|||
const { inputValue } = this.state |
|||
const { isLocked, render } = this.props |
|||
|
|||
if (isLocked) { |
|||
return ( |
|||
<Box sticky align="center" justify="center"> |
|||
<form onSubmit={this.handleSubmit}> |
|||
<Box> |
|||
<Input |
|||
placeholder="Password" |
|||
type="password" |
|||
onChange={this.handleChangeInput('password')} |
|||
value={inputValue.password} |
|||
/> |
|||
</Box> |
|||
</form> |
|||
</Box> |
|||
) |
|||
} |
|||
|
|||
return render() |
|||
} |
|||
} |
|||
|
|||
export default connect(mapStateToProps, mapDispatchToProps, null, { |
|||
pure: false, |
|||
})(IsUnlocked) |
@ -1,15 +1,122 @@ |
|||
// @flow
|
|||
|
|||
import React, { PureComponent } from 'react' |
|||
import styled from 'styled-components' |
|||
import { connect } from 'react-redux' |
|||
import bcrypt from 'bcryptjs' |
|||
|
|||
import get from 'lodash/get' |
|||
import set from 'lodash/set' |
|||
|
|||
import { setEncryptionKey } from 'helpers/db' |
|||
|
|||
import type { MapStateToProps } from 'react-redux' |
|||
import type { Settings } from 'types/common' |
|||
|
|||
import { saveSettings } from 'actions/settings' |
|||
|
|||
import Box from 'components/base/Box' |
|||
import Input from 'components/base/Input' |
|||
import Button from 'components/base/Button' |
|||
|
|||
const Label = styled.label` |
|||
display: block; |
|||
text-transform: uppercase; |
|||
` |
|||
|
|||
type InputValue = Settings |
|||
|
|||
type Props = {} |
|||
type Props = { |
|||
settings: Settings, |
|||
saveSettings: Function, |
|||
} |
|||
type State = { |
|||
inputValue: InputValue, |
|||
} |
|||
|
|||
const mapStateToProps: MapStateToProps<*, *, *> = state => ({ |
|||
settings: state.settings, |
|||
}) |
|||
|
|||
const mapDispatchToProps = { |
|||
saveSettings, |
|||
} |
|||
|
|||
class SettingsPage extends PureComponent<Props, State> { |
|||
state = { |
|||
inputValue: { |
|||
...this.props.settings, |
|||
password: { |
|||
...this.props.settings.password, |
|||
value: undefined, |
|||
}, |
|||
}, |
|||
} |
|||
|
|||
handleChangeInput = (key: $Keys<InputValue>) => (value: $Values<InputValue>) => |
|||
this.setState(prev => ({ |
|||
inputValue: { |
|||
...set(prev.inputValue, key, value), |
|||
}, |
|||
})) |
|||
|
|||
handleSubmit = (e: SyntheticEvent<HTMLFormElement>) => { |
|||
e.preventDefault() |
|||
|
|||
const { saveSettings } = this.props |
|||
const { inputValue } = this.state |
|||
|
|||
const settings = { |
|||
...inputValue, |
|||
password: { |
|||
...inputValue.password, |
|||
value: '', |
|||
}, |
|||
} |
|||
|
|||
const password = get(inputValue, 'password', {}) |
|||
|
|||
if (password.state === true && password.value.trim() !== '') { |
|||
settings.password.value = bcrypt.hashSync(password.value, 8) |
|||
|
|||
setEncryptionKey('accounts', password.value) |
|||
} |
|||
|
|||
saveSettings(settings) |
|||
} |
|||
|
|||
class SettingsPage extends PureComponent<Props> { |
|||
render() { |
|||
return <Box>{'settings'}</Box> |
|||
const { inputValue } = this.state |
|||
|
|||
return ( |
|||
<form onSubmit={this.handleSubmit}> |
|||
<Box p={3}> |
|||
<Box>{'settings'}</Box> |
|||
<Box horizontal> |
|||
<input |
|||
type="checkbox" |
|||
checked={get(inputValue, 'password.state')} |
|||
onChange={e => this.handleChangeInput('password.state')(e.target.checked)} |
|||
/>{' '} |
|||
with password |
|||
</Box> |
|||
{get(inputValue, 'password.state') === true && ( |
|||
<Box> |
|||
<Label>Password</Label> |
|||
<Input |
|||
value={get(inputValue, 'password.value', 'My secure password')} |
|||
onChange={this.handleChangeInput('password.value')} |
|||
type="password" |
|||
/> |
|||
</Box> |
|||
)} |
|||
<Box> |
|||
<Button type="submit">Save</Button> |
|||
</Box> |
|||
</Box> |
|||
</form> |
|||
) |
|||
} |
|||
} |
|||
|
|||
export default SettingsPage |
|||
export default connect(mapStateToProps, mapDispatchToProps)(SettingsPage) |
|||
|
@ -1,7 +1,24 @@ |
|||
import Store from 'electron-store' |
|||
|
|||
const store = new Store({ |
|||
// encryptionKey: 'toto',
|
|||
}) |
|||
const encryptionKey = {} |
|||
|
|||
export default store |
|||
const store = type => |
|||
new Store({ |
|||
name: type, |
|||
defaults: {}, |
|||
encryptionKey: encryptionKey[type], |
|||
}) |
|||
|
|||
export function setEncryptionKey(type, value) { |
|||
encryptionKey[type] = value |
|||
} |
|||
|
|||
export default (type, values) => { |
|||
const db = store(type) |
|||
|
|||
if (values) { |
|||
db.store = values |
|||
} |
|||
|
|||
return db.store |
|||
} |
|||
|
@ -0,0 +1,32 @@ |
|||
// @flow
|
|||
|
|||
import { handleActions, createAction } from 'redux-actions' |
|||
|
|||
import get from 'lodash/get' |
|||
|
|||
export type ApplicationState = {} |
|||
|
|||
const state: ApplicationState = {} |
|||
|
|||
const handlers = { |
|||
APPLICATION_SET_DATA: (state, { payload }: { payload: ApplicationState }) => ({ |
|||
...state, |
|||
...payload, |
|||
}), |
|||
} |
|||
|
|||
// Actions
|
|||
|
|||
export const unlock = createAction('APPLICATION_SET_DATA', () => ({ isLocked: false })) |
|||
export const lock = createAction('APPLICATION_SET_DATA', () => ({ isLocked: true })) |
|||
|
|||
// Selectors
|
|||
|
|||
export const isLocked = (state: Object) => |
|||
state.application.isLocked === undefined |
|||
? get(state.settings, 'password.state', false) |
|||
: state.application.isLocked |
|||
|
|||
// Exporting reducer
|
|||
|
|||
export default handleActions(handlers, state) |
@ -0,0 +1,16 @@ |
|||
// @flow
|
|||
|
|||
import { handleActions } from 'redux-actions' |
|||
|
|||
import type { Settings } from 'types/common' |
|||
|
|||
export type SettingsState = Object |
|||
|
|||
const state: SettingsState = {} |
|||
|
|||
const handlers: Object = { |
|||
SAVE_SETTINGS: (state: SettingsState, { payload: settings }: { payload: Settings }) => settings, |
|||
FETCH_SETTINGS: (state: SettingsState, { payload: settings }: { payload: Settings }) => settings, |
|||
} |
|||
|
|||
export default handleActions(handlers, state) |
Loading…
Reference in new issue