From 2d2e9c4d6e475a03706477556e01fa35ee42115e Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Tue, 25 Oct 2016 17:54:01 +0200 Subject: [PATCH] Add Check and Change Password for an Account (#2861) * Added new RPC endpoints to JSAPI (#2389) * Added modal in Account Page to test & modify password (#2389) * Modify hint with password change // Better tabs (#2556) --- js/src/api/rpc/personal/personal.js | 10 + js/src/modals/PasswordManager/index.js | 17 + .../PasswordManager/passwordManager.css | 73 ++++ .../modals/PasswordManager/passwordManager.js | 383 ++++++++++++++++++ js/src/modals/index.js | 4 +- js/src/ui/Form/Input/input.js | 12 +- js/src/ui/Form/form.js | 12 +- js/src/ui/IdentityName/identityName.js | 7 +- js/src/views/Account/account.js | 42 +- 9 files changed, 550 insertions(+), 10 deletions(-) create mode 100644 js/src/modals/PasswordManager/index.js create mode 100644 js/src/modals/PasswordManager/passwordManager.css create mode 100644 js/src/modals/PasswordManager/passwordManager.js diff --git a/js/src/api/rpc/personal/personal.js b/js/src/api/rpc/personal/personal.js index 2609bc509..e35333102 100644 --- a/js/src/api/rpc/personal/personal.js +++ b/js/src/api/rpc/personal/personal.js @@ -33,6 +33,11 @@ export default class Personal { .execute('personal_confirmRequest', inNumber16(requestId), options, password); } + changePassword (account, password, newPassword) { + return this._transport + .execute('personal_changePassword', inAddress(account), password, newPassword); + } + generateAuthorizationToken () { return this._transport .execute('personal_generateAuthorizationToken'); @@ -105,6 +110,11 @@ export default class Personal { .execute('personal_signerEnabled'); } + testPassword (account, password) { + return this._transport + .execute('personal_testPassword', inAddress(account), password); + } + unlockAccount (account, password, duration = 1) { return this._transport .execute('personal_unlockAccount', inAddress(account), password, inNumber10(duration)); diff --git a/js/src/modals/PasswordManager/index.js b/js/src/modals/PasswordManager/index.js new file mode 100644 index 000000000..9676de163 --- /dev/null +++ b/js/src/modals/PasswordManager/index.js @@ -0,0 +1,17 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +export default from './passwordManager.js'; diff --git a/js/src/modals/PasswordManager/passwordManager.css b/js/src/modals/PasswordManager/passwordManager.css new file mode 100644 index 000000000..aa0f72cb3 --- /dev/null +++ b/js/src/modals/PasswordManager/passwordManager.css @@ -0,0 +1,73 @@ +/* Copyright 2015, 2016 Ethcore (UK) Ltd. +/* This file is part of Parity. +/* +/* Parity is free software: you can redistribute it and/or modify +/* it under the terms of the GNU General Public License as published by +/* the Free Software Foundation, either version 3 of the License, or +/* (at your option) any later version. +/* +/* Parity is distributed in the hope that it will be useful, +/* but WITHOUT ANY WARRANTY; without even the implied warranty of +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/* GNU General Public License for more details. +/* +/* You should have received a copy of the GNU General Public License +/* along with Parity. If not, see . +*/ + +.accountContainer { + display: flex; + flex-direction: row; + margin-bottom: 1.5rem; +} + +.accountInfos { + display: flex; + flex-direction: column; + justify-content: space-around; +} + +.accountInfos > * { + margin: 0.25rem 0; +} + +.hintLabel { + text-transform: uppercase; + font-size: 0.7rem; + margin-right: 0.5rem; +} + +.accountAddress { + font-family: monospace; + font-size: 0.9rem; +} + +.accountName { + font-size: 1.1rem; +} + +.passwordHint { + font-size: 0.9rem; + color: lightgrey; +} + +.message { + margin-top: 1rem; + width: 100%; + height: 2.5rem; + text-align: center; + line-height: 2.5rem; + transition: height 350ms 0 !important; + overflow: hidden; +} + +.hideMessage { + height: 0; + background-color: transparent !important; +} + +.form { + margin-top: 0; + padding: 0 0.5rem 1rem; + background-color: rgba(255, 255, 255, 0.05); +} diff --git a/js/src/modals/PasswordManager/passwordManager.js b/js/src/modals/PasswordManager/passwordManager.js new file mode 100644 index 000000000..800fba929 --- /dev/null +++ b/js/src/modals/PasswordManager/passwordManager.js @@ -0,0 +1,383 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +import React, { Component, PropTypes } from 'react'; +import ContentClear from 'material-ui/svg-icons/content/clear'; +import CheckIcon from 'material-ui/svg-icons/navigation/check'; +import SendIcon from 'material-ui/svg-icons/content/send'; + +import { Tabs, Tab } from 'material-ui/Tabs'; +import Paper from 'material-ui/Paper'; + +import Form, { Input } from '../../ui/Form'; +import { Button, Modal, IdentityName, IdentityIcon } from '../../ui'; + +import styles from './passwordManager.css'; + +const TEST_ACTION = 'TEST_ACTION'; +const CHANGE_ACTION = 'CHANGE_ACTION'; + +export default class PasswordManager extends Component { + static contextTypes = { + api: PropTypes.object.isRequired + } + + static propTypes = { + account: PropTypes.object.isRequired, + onClose: PropTypes.func + } + + state = { + action: TEST_ACTION, + waiting: false, + showMessage: false, + message: { value: '', success: true }, + currentPass: '', + newPass: '', + repeatNewPass: '', + repeatValid: true, + passwordHint: this.props.account.meta && this.props.account.meta.passwordHint || '' + } + + render () { + return ( + + { this.renderAccount() } + { this.renderPage() } + { this.renderMessage() } + + ); + } + + renderMessage () { + const { message, showMessage } = this.state; + + const style = message.success + ? { + backgroundColor: 'rgba(174, 213, 129, 0.75)' + } + : { + backgroundColor: 'rgba(229, 115, 115, 0.75)' + }; + + const classes = [ styles.message ]; + + if (!showMessage) { + classes.push(styles.hideMessage); + } + + return ( + + { message.value } + + ); + } + + renderAccount () { + const { account } = this.props; + const { address, meta } = account; + + const passwordHint = meta && meta.passwordHint + ? ( + + Hint + { meta.passwordHint } + + ) + : null; + + return ( +
+ +
+ + + { address } + + { passwordHint } +
+
+ ); + } + + renderPage () { + const { account } = this.props; + const { waiting, repeatValid } = this.state; + const disabled = !!waiting; + + const repeatError = repeatValid + ? null + : 'the two passwords differ'; + + const { meta } = account; + const passwordHint = meta && meta.passwordHint || ''; + + return ( + + +
+
+ +
+
+
+ +
+
+ + + + + + +
+
+
+
+ ); + } + + renderDialogActions () { + const { onClose } = this.props; + const { action, waiting, repeatValid } = this.state; + + const cancelBtn = ( +