Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Real deleting accounts #3540

Merged
merged 10 commits into from
Nov 24, 2016
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions ethcore/src/account_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,14 +276,20 @@ impl AccountProvider {
}

/// Returns `true` if the password for `account` is `password`. `false` if not.
pub fn test_password(&self, account: &Address, password: String) -> Result<bool, Error> {
match self.sstore.sign(account, &password, &Default::default()) {
pub fn test_password(&self, account: &Address, password: &str) -> Result<bool, Error> {
match self.sstore.sign(account, password, &Default::default()) {
Ok(_) => Ok(true),
Err(SSError::InvalidPassword) => Ok(false),
Err(e) => Err(Error::SStore(e)),
}
}

/// Permanently removes an account.
pub fn kill_account(&self, account: &Address, password: &str) -> Result<(), Error> {
try!(self.sstore.remove_account(account, &password));
Ok(())
}

/// Changes the password of `account` from `password` to `new_password`. Fails if incorrect `password` given.
pub fn change_password(&self, account: &Address, password: String, new_password: String) -> Result<(), Error> {
self.sstore.change_password(account, &password, &new_password).map_err(Error::SStore)
Expand Down
5 changes: 5 additions & 0 deletions js/src/api/rpc/parity/parity.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ export default class Parity {
.then((accounts) => (accounts || []).map(outAddress));
}

killAccount (account, password) {
return this._transport
.execute('parity_killAccount', inAddress(account), password);
}

listGethAccounts () {
return this._transport
.execute('parity_listGethAccounts')
Expand Down
1 change: 1 addition & 0 deletions js/src/api/subscriptions/personal.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export default class Personal {
}

switch (data.method) {
case 'parity_killAccount':
case 'parity_importGethAccounts':
case 'personal_newAccount':
case 'parity_newAccountFromPhrase':
Expand Down
18 changes: 18 additions & 0 deletions js/src/jsonrpc/interfaces/parity.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,24 @@ export default {
}
},

killAccount: {
desc: 'Deletes an account',
params: [
{
type: Address,
desc: 'The account to remove'
},
{
type: String,
desc: 'Account password'
}
],
returns: {
type: Boolean,
desc: 'true on success'
}
},

listGethAccounts: {
desc: 'Returns a list of the accounts available from Geth',
params: [],
Expand Down
54 changes: 54 additions & 0 deletions js/src/modals/DeleteAccount/deleteAccount.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/* 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 <http://www.gnu.org/licenses/>.
*/

.body {
.hero {
padding-bottom: 1em;
}

.info {
display: inline-block;
}

.icon {
display: inline-block;
}

.nameinfo {
display: inline-block;
text-align: left;
}

.header {
text-transform: uppercase;
font-size: 1.25em;
padding-bottom: 0.25em;
}

.address {
}

.description {
padding-top: 1em;
font-size: 0.75em;
color: #aaa;
}

.password {
padding: 1em 5em;
}
}
127 changes: 127 additions & 0 deletions js/src/modals/DeleteAccount/deleteAccount.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// 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 <http://www.gnu.org/licenses/>.

import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

import { ConfirmDialog, IdentityIcon, IdentityName, Input } from '../../ui';
import { newError } from '../../redux/actions';

import styles from './deleteAccount.css';

class DeleteAccount extends Component {
static contextTypes = {
api: PropTypes.object.isRequired,
router: PropTypes.object
}

static propTypes = {
account: PropTypes.object.isRequired,
onClose: PropTypes.func,
newError: PropTypes.func
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the functions are not required?

Consider static defaultProps = { onClose: () => {}, newError: () => () }

}

state = {
password: ''
}

render () {
const { account } = this.props;
const { password } = this.state;

return (
<ConfirmDialog
className={ styles.body }
title='confirm removal'
visible
onDeny={ this.closeDeleteDialog }
onConfirm={ this.onDeleteConfirmed }>
<div className={ styles.hero }>
Are you sure you want to remove permanently delete the following account?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"remove permanently delete"

</div>
<div className={ styles.info }>
<IdentityIcon
className={ styles.icon }
address={ account.address } />
<div className={ styles.nameinfo }>
<div className={ styles.header }>
<IdentityName address={ account.address } unknown />
</div>
<div className={ styles.address }>
{ account.address }
</div>
</div>
</div>
<div className={ styles.description }>
{ account.meta.description }
</div>
<div className={ styles.password }>
<Input
label='account password'
hint='provide the account password to confirm the account deletion'
type='password'
value={ password }
onChange={ this.onChangePassword } />
</div>
</ConfirmDialog>
);
}

onChangePassword = (event, password) => {
this.setState({ password });
}

onDeleteConfirmed = () => {
const { api, router } = this.context;
const { account, newError } = this.props;
const { password } = this.state;

api.parity
.killAccount(account.address, password)
.then((result) => {
if (result === true) {
router.push('/accounts');
} else {
newError(new Error('Deletion failed.'));
}

this.closeDeleteDialog();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really want to close the dialog if there is an error?

})
.catch((error) => {
console.error('onDeleteConfirmed', error);
newError(new Error(`Deletion failed: ${error.message}`));
this.closeDeleteDialog();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really want to close the dialog if there is an error?

});
}

closeDeleteDialog = () => {
this.props.onClose();
}
}

function mapStateToProps (state) {
return {};
}

function mapDispatchToProps (dispatch) {
return bindActionCreators({ newError }, dispatch);
}

export default connect(
mapStateToProps,
mapDispatchToProps
)(DeleteAccount);
17 changes: 17 additions & 0 deletions js/src/modals/DeleteAccount/index.js
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.

export default from './deleteAccount';
2 changes: 2 additions & 0 deletions js/src/modals/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import AddAddress from './AddAddress';
import AddContract from './AddContract';
import CreateAccount from './CreateAccount';
import DeleteAccount from './DeleteAccount';
import DeployContract from './DeployContract';
import EditMeta from './EditMeta';
import ExecuteContract from './ExecuteContract';
Expand All @@ -32,6 +33,7 @@ export {
AddAddress,
AddContract,
CreateAccount,
DeleteAccount,
DeployContract,
EditMeta,
ExecuteContract,
Expand Down
38 changes: 34 additions & 4 deletions js/src/views/Account/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import ActionDelete from 'material-ui/svg-icons/action/delete';
import ContentCreate from 'material-ui/svg-icons/content/create';
import ContentSend from 'material-ui/svg-icons/content/send';
import LockIcon from 'material-ui/svg-icons/action/lock';
import VerifyIcon from 'material-ui/svg-icons/action/verified-user';

import { EditMeta, Shapeshift, SMSVerification, Transfer, PasswordManager } from '../../modals';
import { EditMeta, DeleteAccount, Shapeshift, SMSVerification, Transfer, PasswordManager } from '../../modals';
import { Actionbar, Button, Page } from '../../ui';

import shapeshiftBtn from '../../../assets/images/shapeshift-btn.png';
Expand Down Expand Up @@ -50,6 +51,7 @@ class Account extends Component {
propName = null

state = {
showDeleteDialog: false,
showEditDialog: false,
showFundDialog: false,
showVerificationDialog: false,
Expand All @@ -62,8 +64,8 @@ class Account extends Component {
const { api } = this.context;
const { address } = this.props.params;

const store = new VerificationStore(api, address);
this.setState({ verificationStore: store });
const verificationStore = new VerificationStore(api, address);
this.setState({ verificationStore });
}

render () {
Expand All @@ -79,6 +81,7 @@ class Account extends Component {

return (
<div className={ styles.account }>
{ this.renderDeleteDialog(account) }
{ this.renderEditDialog(account) }
{ this.renderFundDialog() }
{ this.renderVerificationDialog() }
Expand Down Expand Up @@ -131,7 +134,12 @@ class Account extends Component {
key='passwordManager'
icon={ <LockIcon /> }
label='password'
onClick={ this.onPasswordClick } />
onClick={ this.onPasswordClick } />,
<Button
key='delete'
icon={ <ActionDelete /> }
label='delete account'
onClick={ this.onDeleteClick } />
];

return (
Expand All @@ -141,6 +149,20 @@ class Account extends Component {
);
}

renderDeleteDialog (account) {
const { showDeleteDialog } = this.state;

if (!showDeleteDialog) {
return null;
}

return (
<DeleteAccount
account={ account }
onClose={ this.onDeleteClose } />
);
}

renderEditDialog (account) {
const { showEditDialog } = this.state;

Expand Down Expand Up @@ -228,6 +250,14 @@ class Account extends Component {
);
}

onDeleteClick = () => {
this.setState({ showDeleteDialog: true });
}

onDeleteClose = () => {
this.setState({ showDeleteDialog: false });
}

onEditClick = () => {
this.setState({
showEditDialog: !this.state.showEditDialog
Expand Down
Loading