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; break;
case 'payload': 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].signTransaction = outTransaction(request[key].signTransaction);
request[key].sendTransaction = outTransaction(request[key].sendTransaction); request[key].sendTransaction = outTransaction(request[key].sendTransaction);
break; break;
@ -296,6 +298,20 @@ export function outTransaction (tx) {
return 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) { export function outTrace (trace) {
if (trace) { if (trace) {
if (trace.action) { 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 { .hash {
margin-left: .2em; margin-left: .5em;
} }
.hash, .url { .hash, .url {

View File

@ -16,8 +16,9 @@
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
import TransactionPending from '../TransactionPending'; import DecryptRequest from '../DecryptRequest';
import SignRequest from '../SignRequest'; import SignRequest from '../SignRequest';
import TransactionPending from '../TransactionPending';
export default class RequestPending extends Component { export default class RequestPending extends Component {
static propTypes = { static propTypes = {
@ -32,6 +33,7 @@ export default class RequestPending extends Component {
onReject: PropTypes.func.isRequired, onReject: PropTypes.func.isRequired,
origin: PropTypes.object.isRequired, origin: PropTypes.object.isRequired,
payload: PropTypes.oneOfType([ payload: PropTypes.oneOfType([
PropTypes.shape({ decrypt: PropTypes.object.isRequired }),
PropTypes.shape({ sendTransaction: PropTypes.object.isRequired }), PropTypes.shape({ sendTransaction: PropTypes.object.isRequired }),
PropTypes.shape({ sign: PropTypes.object.isRequired }), PropTypes.shape({ sign: PropTypes.object.isRequired }),
PropTypes.shape({ signTransaction: 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; const transaction = payload.sendTransaction || payload.signTransaction;
if (transaction) { if (transaction) {

View File

@ -19,7 +19,7 @@
.container { .container {
display: flex; display: flex;
padding: 1.5em 0 1em; padding: 1.5em 1em 1.5em 0;
} }
.actions, .signDetails { .actions, .signDetails {
@ -28,35 +28,43 @@
} }
.signData { .signData {
border: 0.25em solid red; border: 0.25em solid red;
padding: 0.5em; margin-left: 2em;
margin-left: -2em; padding: 0.5em;
overflow: auto; overflow: auto;
max-height: 6em; max-height: 6em;
max-width: calc(100% - 2em);
} }
.signData > p { .signData > p {
color: white; color: white;
} }
.signDetails { .signDetails {
flex: 10; flex: 1;
overflow: auto;
}
.account img {
display: inline-block;
height: 50px;
margin: 5px;
width: 50px;
} }
.address, .info { .address, .info {
box-sizing: border-box; box-sizing: border-box;
display: inline-block; display: inline-block;
width: 50%; vertical-align: top;
} }
.address { .address {
padding-right: $accountPadding; width: 40%;
} }
.info { .info {
padding: 0 30px;
color: #E53935; color: #E53935;
vertical-align: top; width: 60%;
} }
.info p:first-child { .info p:first-child {
@ -81,10 +89,3 @@
display: inline-block; display: inline-block;
min-height: $finishedHeight; 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 <Account
address={ address } address={ address }
balance={ balance } balance={ balance }
className={ styles.account }
externalLink={ externalLink } externalLink={ externalLink }
netVersion={ netVersion } netVersion={ netVersion }
/> />
@ -155,9 +156,7 @@ class SignRequest extends Component {
renderActions () { renderActions () {
const { accounts, address, focus, isFinished, status } = this.props; const { accounts, address, focus, isFinished, status } = this.props;
const account = Object const account = accounts[address];
.values(accounts)
.find((account) => address === account.address.toLowerCase());
if (isFinished) { if (isFinished) {
if (status === 'confirmed') { if (status === 'confirmed') {
@ -191,6 +190,7 @@ class SignRequest extends Component {
address={ address } address={ address }
focus={ focus } focus={ focus }
isSending={ this.props.isSending } isSending={ this.props.isSending }
netVersion={ this.props.netVersion }
onConfirm={ this.onConfirm } onConfirm={ this.onConfirm }
onReject={ this.onReject } onReject={ this.onReject }
className={ styles.actions } className={ styles.actions }