Add decryption to the UI (in the Signer) (#5422)

* Add decryption to the UI in signer + Fix Signing style

* Proper out format function for singing methods

* name
This commit is contained in:
Nicolas Gotchac 2017-04-10 05:21:06 -04:00 committed by Gav Wood
parent 20d4e7139f
commit 0aaf236ad1
7 changed files with 264 additions and 24 deletions

View File

@ -216,6 +216,8 @@ export function outSignerRequest (request) {
break;
case 'payload':
request[key].decrypt = outSigningPayload(request[key].decrypt);
request[key].sign = outSigningPayload(request[key].sign);
request[key].signTransaction = outTransaction(request[key].signTransaction);
request[key].sendTransaction = outTransaction(request[key].sendTransaction);
break;
@ -296,6 +298,20 @@ export function outTransaction (tx) {
return tx;
}
export function outSigningPayload (payload) {
if (payload) {
Object.keys(payload).forEach((key) => {
switch (key) {
case 'address':
payload[key] = outAddress(payload[key]);
break;
}
});
}
return payload;
}
export function outTrace (trace) {
if (trace) {
if (trace.action) {

View File

@ -0,0 +1,183 @@
// Copyright 2015-2017 Parity Technologies (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 { observer } from 'mobx-react';
import React, { Component, PropTypes } from 'react';
import { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
import Account from '../Account';
import TransactionPendingForm from '../TransactionPendingForm';
import RequestOrigin from '../RequestOrigin';
import styles from '../SignRequest/signRequest.css';
@observer
class DecryptRequest extends Component {
static contextTypes = {
api: PropTypes.object
};
static propTypes = {
accounts: PropTypes.object.isRequired,
address: PropTypes.string.isRequired,
data: PropTypes.string.isRequired,
id: PropTypes.object.isRequired,
isFinished: PropTypes.bool.isRequired,
netVersion: PropTypes.string.isRequired,
signerStore: PropTypes.object.isRequired,
className: PropTypes.string,
focus: PropTypes.bool,
isSending: PropTypes.bool,
onConfirm: PropTypes.func,
onReject: PropTypes.func,
origin: PropTypes.any,
status: PropTypes.string
};
static defaultProps = {
focus: false,
origin: {
type: 'unknown',
details: ''
}
};
componentWillMount () {
const { address, signerStore } = this.props;
signerStore.fetchBalance(address);
}
render () {
const { className } = this.props;
return (
<div className={ `${styles.container} ${className}` }>
{ this.renderDetails() }
{ this.renderActions() }
</div>
);
}
renderDetails () {
const { api } = this.context;
const { address, data, netVersion, origin, signerStore } = this.props;
const { balances, externalLink } = signerStore;
const balance = balances[address];
if (!balance) {
return <div />;
}
return (
<div className={ styles.signDetails }>
<div className={ styles.address }>
<Account
address={ address }
balance={ balance }
className={ styles.account }
externalLink={ externalLink }
netVersion={ netVersion }
/>
<RequestOrigin origin={ origin } />
</div>
<div className={ styles.info } title={ api.util.sha3(data) }>
<p>
<FormattedMessage
id='signer.decryptRequest.request'
defaultMessage='A request to decrypt data using your account:'
/>
</p>
<div className={ styles.signData }>
<p>{ data }</p>
</div>
</div>
</div>
);
}
renderActions () {
const { accounts, address, focus, isFinished, status } = this.props;
const account = accounts[address];
if (isFinished) {
if (status === 'confirmed') {
return (
<div className={ styles.actions }>
<span className={ styles.isConfirmed }>
<FormattedMessage
id='signer.decryptRequest.state.confirmed'
defaultMessage='Confirmed'
/>
</span>
</div>
);
}
return (
<div className={ styles.actions }>
<span className={ styles.isRejected }>
<FormattedMessage
id='signer.decryptRequest.state.rejected'
defaultMessage='Rejected'
/>
</span>
</div>
);
}
return (
<TransactionPendingForm
account={ account }
address={ address }
focus={ focus }
isSending={ this.props.isSending }
netVersion={ this.props.netVersion }
onConfirm={ this.onConfirm }
onReject={ this.onReject }
className={ styles.actions }
/>
);
}
onConfirm = (data) => {
const { id } = this.props;
const { password } = data;
this.props.onConfirm({ id, password });
}
onReject = () => {
this.props.onReject(this.props.id);
}
}
function mapStateToProps (state) {
const { accounts } = state.personal;
return {
accounts
};
}
export default connect(
mapStateToProps,
null
)(DecryptRequest);

View File

@ -0,0 +1,17 @@
// Copyright 2015-2017 Parity Technologies (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 './decryptRequest';

View File

@ -33,7 +33,7 @@
}
.hash {
margin-left: .2em;
margin-left: .5em;
}
.hash, .url {

View File

@ -16,8 +16,9 @@
import React, { Component, PropTypes } from 'react';
import TransactionPending from '../TransactionPending';
import DecryptRequest from '../DecryptRequest';
import SignRequest from '../SignRequest';
import TransactionPending from '../TransactionPending';
export default class RequestPending extends Component {
static propTypes = {
@ -32,6 +33,7 @@ export default class RequestPending extends Component {
onReject: PropTypes.func.isRequired,
origin: PropTypes.object.isRequired,
payload: PropTypes.oneOfType([
PropTypes.shape({ decrypt: PropTypes.object.isRequired }),
PropTypes.shape({ sendTransaction: PropTypes.object.isRequired }),
PropTypes.shape({ sign: PropTypes.object.isRequired }),
PropTypes.shape({ signTransaction: PropTypes.object.isRequired })
@ -68,6 +70,27 @@ export default class RequestPending extends Component {
);
}
if (payload.decrypt) {
const { decrypt } = payload;
return (
<DecryptRequest
address={ decrypt.address }
className={ className }
focus={ focus }
data={ decrypt.msg }
id={ id }
isFinished={ false }
isSending={ isSending }
netVersion={ netVersion }
onConfirm={ this.onConfirm }
onReject={ onReject }
origin={ origin }
signerStore={ signerStore }
/>
);
}
const transaction = payload.sendTransaction || payload.signTransaction;
if (transaction) {

View File

@ -19,7 +19,7 @@
.container {
display: flex;
padding: 1.5em 0 1em;
padding: 1.5em 1em 1.5em 0;
}
.actions, .signDetails {
@ -29,10 +29,11 @@
.signData {
border: 0.25em solid red;
margin-left: 2em;
padding: 0.5em;
margin-left: -2em;
overflow: auto;
max-height: 6em;
max-width: calc(100% - 2em);
}
.signData > p {
@ -40,23 +41,30 @@
}
.signDetails {
flex: 10;
flex: 1;
overflow: auto;
}
.account img {
display: inline-block;
height: 50px;
margin: 5px;
width: 50px;
}
.address, .info {
box-sizing: border-box;
display: inline-block;
width: 50%;
vertical-align: top;
}
.address {
padding-right: $accountPadding;
width: 40%;
}
.info {
padding: 0 30px;
color: #E53935;
vertical-align: top;
width: 60%;
}
.info p:first-child {
@ -81,10 +89,3 @@
display: inline-block;
min-height: $finishedHeight;
}
.signDetails img {
display: inline-block;
width: 50px;
height: 50px;
margin: 5px;
}

View File

@ -123,6 +123,7 @@ class SignRequest extends Component {
<Account
address={ address }
balance={ balance }
className={ styles.account }
externalLink={ externalLink }
netVersion={ netVersion }
/>
@ -155,9 +156,7 @@ class SignRequest extends Component {
renderActions () {
const { accounts, address, focus, isFinished, status } = this.props;
const account = Object
.values(accounts)
.find((account) => address === account.address.toLowerCase());
const account = accounts[address];
if (isFinished) {
if (status === 'confirmed') {
@ -191,6 +190,7 @@ class SignRequest extends Component {
address={ address }
focus={ focus }
isSending={ this.props.isSending }
netVersion={ this.props.netVersion }
onConfirm={ this.onConfirm }
onReject={ this.onReject }
className={ styles.actions }