Filter request popups (#5843)

* Formatting

* Update dapps to use web3Provider

* Remove secure flag from config

* Basic request approve/reject popup

* Lenient provider checks

* Case sensitivity fix
This commit is contained in:
Jaco Greeff 2017-06-14 17:12:13 +02:00 committed by GitHub
parent 38b4ba8d33
commit 58f15f1674
35 changed files with 338 additions and 135 deletions

View File

@ -30,11 +30,7 @@ export default class Api extends EventEmitter {
constructor (provider, allowSubscriptions = true) { constructor (provider, allowSubscriptions = true) {
super(); super();
if (!provider || (!isFunction(provider.send) && !isFunction(provider.execute))) { if (!provider || !isFunction(provider.send)) {
throw new Error('Api needs provider with send() function');
}
if (!isFunction(provider.send)) {
console.warn(new Error('deprecated: Api needs provider with send() function, old-style Transport found instead')); console.warn(new Error('deprecated: Api needs provider with send() function, old-style Transport found instead'));
} }

View File

@ -22,18 +22,6 @@ import util from './util';
import Api from './api'; import Api from './api';
describe('api/Api', () => { describe('api/Api', () => {
describe('constructor', () => {
it('requires defined/non-null provider object', () => {
expect(() => new Api()).to.throw(/Api needs provider/);
expect(() => new Api(null)).to.throw(/Api needs provider/);
});
it('requires an send function on the transport object', () => {
expect(() => new Api({})).to.throw(/Api needs provider/);
expect(() => new Api({ send: true })).to.throw(/Api needs provider/);
});
});
describe('interface', () => { describe('interface', () => {
const api = new Api(new Api.Provider.Http(TEST_HTTP_URL, -1)); const api = new Api(new Api.Provider.Http(TEST_HTTP_URL, -1));

View File

@ -46,7 +46,11 @@ export default class PostMessage {
return; return;
} }
this._callbacks[id](error, result); if (error) {
console.error(from, error);
}
this._callbacks[id](error && new Error(error), result);
this._callbacks[id] = null; this._callbacks[id] = null;
} }
} }

View File

@ -14,7 +14,10 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
const api = window.parity.api; import Api from '@parity/api';
const web3Provider = (window.parity && window.parity.web3Provider) || (window.parent && window.parent.web3Provider);
const api = new Api(web3Provider);
export { export {
api api

View File

@ -15,8 +15,11 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import Web3 from 'web3'; import Web3 from 'web3';
import Api from '@parity/api';
const web3Provider = (window.parity && window.parity.web3Provider) || (window.parent && window.parent.web3Provider);
const api = new Api(web3Provider);
const api = window.parent.secureApi;
let web3; let web3;
api.parity.dappsUrl().then(url => { api.parity.dappsUrl().then(url => {

View File

@ -14,7 +14,10 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
const api = window.parent.secureApi; import Api from '@parity/api';
const web3Provider = (window.parity && window.parity.web3Provider) || (window.parent && window.parent.web3Provider);
const api = new Api(web3Provider);
function trackRequest (signerRequestId, statusCallback) { function trackRequest (signerRequestId, statusCallback) {
return api.pollMethod('parity_checkRequest', signerRequestId) return api.pollMethod('parity_checkRequest', signerRequestId)

View File

@ -22,7 +22,6 @@
} }
.container { .container {
font-family: 'Roboto';
vertical-align: middle; vertical-align: middle;
padding: 4em 0; padding: 4em 0;
margin: 0 0 2em 0; margin: 0 0 2em 0;

View File

@ -14,7 +14,10 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
const api = window.parent.secureApi; import Api from '@parity/api';
const web3Provider = (window.parity && window.parity.web3Provider) || (window.parent && window.parent.web3Provider);
const api = new Api(web3Provider);
export { export {
api api

View File

@ -12,7 +12,7 @@
margin: 0; margin: 0;
padding: 0; padding: 0;
background: white; background: white;
font-family: 'Roboto', sans-serif; font-family: 'Roboto', 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Geneva, Arial, sans-serif;
font-size: 16px; font-size: 16px;
font-weight: 300; font-weight: 300;
} }
@ -30,8 +30,5 @@
<div class="loading">Loading</div> <div class="loading">Loading</div>
</div> </div>
<script src="vendor.js"></script> <script src="vendor.js"></script>
<% if (!htmlWebpackPlugin.options.secure) { %>
<script src="/parity-utils/parity.js"></script>
<% } %>
</body> </body>
</html> </html>

View File

@ -14,7 +14,10 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
const api = window.parent.secureApi; import Api from '@parity/api';
const web3Provider = (window.parity && window.parity.web3Provider) || (window.parent && window.parent.web3Provider);
const api = new Api(web3Provider);
export { export {
api api

View File

@ -14,8 +14,11 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
const api = window.parity.api; import Api from '@parity/api';
const { bytesToHex, sha3, toWei, fromWei } = window.parity.api.util;
const web3Provider = (window.parity && window.parity.web3Provider) || (window.parent && window.parent.web3Provider);
const api = new Api(web3Provider);
const { bytesToHex, sha3, toWei, fromWei } = api.util;
export { export {
api, api,

View File

@ -18,7 +18,6 @@
.container { .container {
background: black; background: black;
color: #eee; color: #eee;
font-family: 'Roboto';
vertical-align: middle; vertical-align: middle;
} }

View File

@ -79,7 +79,7 @@
padding: 1em; padding: 1em;
color: #eee; color: #eee;
font-size: 0.75em; font-size: 0.75em;
font-family: 'Roboto Mono'; font-family: 'Roboto Mono', monospace;
width: 100%; width: 100%;
border: none; border: none;
box-sizing: border-box; box-sizing: border-box;

View File

@ -14,7 +14,10 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
const { api } = window.parity; import Api from '@parity/api';
const web3Provider = (window.parity && window.parity.web3Provider) || (window.parent && window.parent.web3Provider);
const api = new Api(web3Provider);
export { export {
api api

View File

@ -21,7 +21,7 @@
border: 0; border: 0;
color: #333; color: #333;
font-size: 16px; font-size: 16px;
font-family: 'Roboto', sans-serif; font-family: 'Roboto', 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Geneva, Arial, sans-serif;
font-weight: 300; font-weight: 300;
margin: 0; margin: 0;
padding: 0; padding: 0;

View File

@ -17,7 +17,6 @@
.container { .container {
color: #444; color: #444;
font-family: 'Roboto';
vertical-align: middle; vertical-align: middle;
min-height: 100vh; min-height: 100vh;
position:relative; position:relative;

View File

@ -14,7 +14,10 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
const { api } = window.parity; import Api from '@parity/api';
const web3Provider = (window.parity && window.parity.web3Provider) || (window.parent && window.parent.web3Provider);
const api = new Api(web3Provider);
export { export {
api api

View File

@ -14,7 +14,10 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
const api = window.parent.secureApi; import Api from '@parity/api';
const web3Provider = (window.parity && window.parity.web3Provider) || (window.parent && window.parent.web3Provider);
const api = new Api(web3Provider);
export { export {
api api

View File

@ -16,8 +16,7 @@
"version": "0.3", "version": "0.3",
"author": "Gav Wood <gavin@parity.io>", "author": "Gav Wood <gavin@parity.io>",
"position": "top-right", "position": "top-right",
"visible": true, "visible": true
"secure": true
}, },
{ {
"id": "0xf9f2d620c2e08f83e45555247146c62185e4ab7cf82a4b9002a265a0d020348f", "id": "0xf9f2d620c2e08f83e45555247146c62185e4ab7cf82a4b9002a265a0d020348f",
@ -44,8 +43,7 @@
"description": "A registry of transactable tokens on the network", "description": "A registry of transactable tokens on the network",
"author": "Parity Team <admin@parity.io>", "author": "Parity Team <admin@parity.io>",
"version": "1.0.0", "version": "1.0.0",
"visible": true, "visible": true
"secure": true
}, },
{ {
"id": "0xf49089046f53f5d2e5f3513c1c32f5ff57d986e46309a42d2b249070e4e72c46", "id": "0xf49089046f53f5d2e5f3513c1c32f5ff57d986e46309a42d2b249070e4e72c46",
@ -64,7 +62,6 @@
"author": "Parity Team <admin@parity.io>", "author": "Parity Team <admin@parity.io>",
"version": "1.0.0", "version": "1.0.0",
"visible": false, "visible": false,
"secure": true,
"onlyPersonal": true "onlyPersonal": true
}, },
{ {
@ -74,8 +71,7 @@
"description": "Have a peek at the internals of your node's transaction queue", "description": "Have a peek at the internals of your node's transaction queue",
"author": "Parity Team <admin@parity.io>", "author": "Parity Team <admin@parity.io>",
"version": "1.0.0", "version": "1.0.0",
"visible": true, "visible": true
"secure": true
}, },
{ {
"id": "0x7bbc4f1a27628781b96213e781a1b8eec6982c1db8fac739af6e4c5a55862c03", "id": "0x7bbc4f1a27628781b96213e781a1b8eec6982c1db8fac739af6e4c5a55862c03",
@ -84,8 +80,7 @@
"description": "Enables the registration and content management of dapps on the network", "description": "Enables the registration and content management of dapps on the network",
"author": "Parity Team <admin@parity.io>", "author": "Parity Team <admin@parity.io>",
"version": "1.0.0", "version": "1.0.0",
"visible": false, "visible": false
"secure": true
}, },
{ {
"id": "0x9042323cd85c6576992d211de34b3ecc183f15e4f639aa87859882f839c374e5", "id": "0x9042323cd85c6576992d211de34b3ecc183f15e4f639aa87859882f839c374e5",

View File

@ -7,8 +7,7 @@
"description": "Display the accounts", "description": "Display the accounts",
"author": "Parity Team <admin@ethcore.io>", "author": "Parity Team <admin@ethcore.io>",
"version": "2.0.0", "version": "2.0.0",
"visible": true, "visible": true
"secure": true
}, },
{ {
"id": "account", "id": "account",
@ -19,7 +18,6 @@
"author": "Parity Team <admin@ethcore.io>", "author": "Parity Team <admin@ethcore.io>",
"version": "2.0.0", "version": "2.0.0",
"visible": true, "visible": true,
"secure": true,
"noselect": true "noselect": true
}, },
{ {
@ -30,8 +28,7 @@
"description": "Display the accounts added to the addressbook", "description": "Display the accounts added to the addressbook",
"author": "Parity Team <admin@ethcore.io>", "author": "Parity Team <admin@ethcore.io>",
"version": "2.0.0", "version": "2.0.0",
"visible": true, "visible": true
"secure": true
}, },
{ {
"id": "address", "id": "address",
@ -42,7 +39,6 @@
"author": "Parity Team <admin@ethcore.io>", "author": "Parity Team <admin@ethcore.io>",
"version": "2.0.0", "version": "2.0.0",
"visible": true, "visible": true,
"secure": true,
"noselect": true "noselect": true
}, },
{ {
@ -53,8 +49,7 @@
"description": "Display the contracts added to the addressbook", "description": "Display the contracts added to the addressbook",
"author": "Parity Team <admin@ethcore.io>", "author": "Parity Team <admin@ethcore.io>",
"version": "2.0.0", "version": "2.0.0",
"visible": true, "visible": true
"secure": true
}, },
{ {
"id": "contract", "id": "contract",
@ -65,7 +60,6 @@
"author": "Parity Team <admin@ethcore.io>", "author": "Parity Team <admin@ethcore.io>",
"version": "2.0.0", "version": "2.0.0",
"visible": true, "visible": true,
"secure": true,
"noselect": true "noselect": true
}, },
{ {
@ -76,8 +70,7 @@
"description": "Create new contracts", "description": "Create new contracts",
"author": "Parity Team <admin@ethcore.io>", "author": "Parity Team <admin@ethcore.io>",
"version": "2.0.0", "version": "2.0.0",
"visible": true, "visible": true
"secure": true
}, },
{ {
"id": "home", "id": "home",
@ -87,8 +80,7 @@
"description": "Display the status of the node, recently accessed applications, accounts and news", "description": "Display the status of the node, recently accessed applications, accounts and news",
"author": "Parity Team <admin@ethcore.io>", "author": "Parity Team <admin@ethcore.io>",
"version": "2.0.0", "version": "2.0.0",
"visible": true, "visible": true
"secure": true
}, },
{ {
"id": "playground", "id": "playground",
@ -99,7 +91,6 @@
"author": "Parity Team <admin@ethcore.io>", "author": "Parity Team <admin@ethcore.io>",
"version": "2.0.0", "version": "2.0.0",
"visible": true, "visible": true,
"secure": true,
"noselect": true "noselect": true
}, },
{ {
@ -110,8 +101,7 @@
"description": "Display the current and historic Signer requests", "description": "Display the current and historic Signer requests",
"author": "Parity Team <admin@ethcore.io>", "author": "Parity Team <admin@ethcore.io>",
"version": "2.0.0", "version": "2.0.0",
"visible": true, "visible": true
"secure": true
}, },
{ {
"id": "settings", "id": "settings",
@ -121,8 +111,7 @@
"description": "Allows the configuraion of all Parity & Parity-UI related options", "description": "Allows the configuraion of all Parity & Parity-UI related options",
"author": "Parity Team <admin@ethcore.io>", "author": "Parity Team <admin@ethcore.io>",
"version": "2.0.0", "version": "2.0.0",
"visible": true, "visible": true
"secure": true
}, },
{ {
"id": "status", "id": "status",
@ -132,8 +121,7 @@
"description": "Displays an overview of the node including settings, logs and connections", "description": "Displays an overview of the node including settings, logs and connections",
"author": "Parity Team <admin@ethcore.io>", "author": "Parity Team <admin@ethcore.io>",
"version": "2.0.0", "version": "2.0.0",
"visible": true, "visible": true
"secure": true
}, },
{ {
"id": "vaults", "id": "vaults",
@ -143,8 +131,7 @@
"description": "Allows the management of the Account Vaults, including creation, locking and account assignment", "description": "Allows the management of the Account Vaults, including creation, locking and account assignment",
"author": "Parity Team <admin@ethcore.io>", "author": "Parity Team <admin@ethcore.io>",
"version": "2.0.0", "version": "2.0.0",
"visible": true, "visible": true
"secure": true
}, },
{ {
"id": "wallet", "id": "wallet",
@ -155,7 +142,6 @@
"author": "Parity Team <admin@ethcore.io>", "author": "Parity Team <admin@ethcore.io>",
"version": "2.0.0", "version": "2.0.0",
"visible": true, "visible": true,
"secure": true,
"noselect": true "noselect": true
}, },
{ {
@ -167,7 +153,6 @@
"author": "Parity Team <admin@ethcore.io>", "author": "Parity Team <admin@ethcore.io>",
"version": "2.0.0", "version": "2.0.0",
"visible": true, "visible": true,
"secure": true,
"noselect": true "noselect": true
} }
] ]

View File

@ -22,6 +22,7 @@ import { connect } from 'react-redux';
import { Errors } from '@parity/ui'; import { Errors } from '@parity/ui';
import Connection from '../Connection'; import Connection from '../Connection';
import DappFilter from '../DappFilter';
import Extension from '../Extension'; import Extension from '../Extension';
import FirstRun from '../FirstRun'; import FirstRun from '../FirstRun';
import ParityBar from '../ParityBar'; import ParityBar from '../ParityBar';
@ -82,6 +83,7 @@ class Application extends Component {
: null : null
} }
<Connection /> <Connection />
<DappFilter />
<Requests /> <Requests />
<ParityBar dapp={ isMinimized } /> <ParityBar dapp={ isMinimized } />
</div> </div>

View File

@ -21,7 +21,7 @@ import { FormattedMessage } from 'react-intl';
import { AccountCard, Portal, SelectionList } from '@parity/ui'; import { AccountCard, Portal, SelectionList } from '@parity/ui';
@observer @observer
export default class DappPermissions extends Component { export default class DappAccounts extends Component {
static propTypes = { static propTypes = {
permissionStore: PropTypes.object.isRequired permissionStore: PropTypes.object.isRequired
}; };
@ -39,7 +39,7 @@ export default class DappPermissions extends Component {
open open
title={ title={
<FormattedMessage <FormattedMessage
id='dapps.permissions.label' id='dapps.accounts.label'
defaultMessage='visible dapp accounts' defaultMessage='visible dapp accounts'
/> />
} }

View File

@ -17,19 +17,19 @@
import { shallow } from 'enzyme'; import { shallow } from 'enzyme';
import React from 'react'; import React from 'react';
import DappPermissions from './'; import DappAccounts from './';
let component; let component;
function renderShallow (permissionStore = {}) { function renderShallow (permissionStore = {}) {
component = shallow( component = shallow(
<DappPermissions permissionStore={ permissionStore } /> <DappAccounts permissionStore={ permissionStore } />
); );
return component; return component;
} }
describe('shell/DappPermissions', () => { describe('shell/DappAccounts', () => {
describe('rendering', () => { describe('rendering', () => {
it('renders defaults', () => { it('renders defaults', () => {
expect(renderShallow()).to.be.ok; expect(renderShallow()).to.be.ok;

View File

@ -14,4 +14,4 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
export default from './dappPermissions'; export default from './dappAccounts';

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 './request';

View File

@ -0,0 +1,64 @@
// 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 React, { PropTypes } from 'react';
import { FormattedMessage } from 'react-intl';
import { Button } from '@parity/ui';
export default function Request ({ className, approveRequest, denyRequest, queueId, request: { from, method } }) {
const _onApprove = () => approveRequest(queueId);
const _onReject = () => denyRequest(queueId);
return (
<div className={ className }>
<FormattedMessage
id='dappFilter.request.info'
defaultMessage='Received request from {method} from {from}'
values={ {
from,
method
} }
/>
<Button
label={
<FormattedMessage
id='dappFilter.request.buttons.approve'
defaultMessage='Approve request'
/>
}
onClick={ _onApprove }
/>
<Button
label={
<FormattedMessage
id='dappFilter.request.buttons.reject'
defaultMessage='Reject request'
/>
}
onClick={ _onReject }
/>
</div>
);
}
Request.propTypes = {
className: PropTypes.string,
approveRequest: PropTypes.func.isRequired,
denyRequest: PropTypes.func.isRequired,
queueId: PropTypes.number.isRequired,
request: PropTypes.object.isRequired
};

View File

@ -0,0 +1,34 @@
/* 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/>.
*/
.filter {
background: #f80;
color: white;
bottom: 0;
position: fixed;
left: 0;
right: 0;
z-index: 760; /* sits above requests */
.request {
padding: 0.5em;
> span {
margin-right: 1em;
}
}
}

View File

@ -14,52 +14,36 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
export default class DappFilter { import { observer } from 'mobx-react';
constructor (provider, permissions) { import React from 'react';
this.permissions = permissions;
this.provider = provider;
window.addEventListener('message', this.receiveMessage, false); import Request from './Request';
import Store from './store';
import styles from './dappFilter.css';
function DappFilter () {
const store = Store.get();
if (!store || !store.hasRequests) {
return null;
} }
receiveMessage = ({ data: { id, from, method, params, token }, origin, source }) => { return (
if (from === 'shell' || from !== token) { <div className={ styles.filter }>
return; {
} store.requests.map(({ queueId, request: { data } }) => (
<Request
if (this.permissions.filtered.includes(method) && !this.permissions.tokens[token][method]) { className={ styles.request }
source.postMessage({ approveRequest={ store.approveRequest }
id, denyRequest={ store.rejectRequest }
from: 'shell', key={ queueId }
error: new Error(`Method ${method} is not available to application`), queueId={ queueId }
result: null, request={ data }
token />
}, '*'); ))
return; }
} </div>
);
this.provider.send(method, params, (error, result) => {
source.postMessage({
error,
id,
from: 'shell',
result,
token
}, '*');
});
}
setPermissions (permissions) {
this.permissions = permissions;
}
static instance = null;
static create (provider, permissions) {
DappFilter.instance = new DappFilter(provider, permissions);
}
static get () {
return DappFilter.instance;
}
} }
export default observer(DappFilter);

View File

@ -14,4 +14,5 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
export Store from './store';
export default from './dappFilter'; export default from './dappFilter';

View File

@ -0,0 +1,114 @@
// 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 { action, computed, observable } from 'mobx';
let nextQueueId = 0;
export default class Store {
@observable permissions = [];
@observable requests = [];
constructor (provider, permissions) {
this.permissions = permissions;
this.provider = provider;
window.addEventListener('message', this.receiveMessage, false);
}
@computed get hasRequests () {
return this.requests.length !== 0;
}
@action removeRequest = (_queueId) => {
this.requests = this.requests.filter(({ queueId }) => queueId !== _queueId);
}
@action queueRequest = (request) => {
let queueId = ++nextQueueId;
this.requests = this.requests.concat([{ queueId, request }]);
}
@action approveRequest = (queueId) => {
const { request: { data, source } } = this.findRequest(queueId);
this.removeRequest(queueId);
this.executeOnProvider(data, source);
}
@action rejectRequest = (queueId) => {
const { request: { data: { id, method, token }, source } } = this.findRequest(queueId);
this.removeRequest(queueId);
source.postMessage({
error: `Method ${method} not allowed`,
id,
from: 'shell',
result: null,
token
}, '*');
}
@action setPermissions = (permissions) => {
this.permissions = permissions;
}
findRequest (_queueId) {
return this.requests.find(({ queueId }) => queueId === _queueId);
}
executeOnProvider = ({ id, from, method, params, token }, source) => {
this.provider.send(method, params, (error, result) => {
source.postMessage({
error: error
? error.message
: null,
id,
from: 'shell',
result,
token
}, '*');
});
}
receiveMessage = ({ data, origin, source }) => {
const { from, method, token } = data;
if (from === 'shell' || from !== token) {
return;
}
if (this.permissions.filtered.includes(method)) {
if (!this.permissions.tokens[token] || !this.permissions.tokens[token][method]) {
this.queueRequest({ data, origin, source });
return;
}
}
this.executeOnProvider(data, source);
}
static instance = null;
static create (provider, permissions) {
Store.instance = new Store(provider, permissions);
}
static get () {
return Store.instance;
}
}

View File

@ -24,8 +24,8 @@ import { Actionbar, Button, Checkbox, DappCard, Page, SectionList } from '@parit
import { LockedIcon, VisibleIcon } from '@parity/ui/Icons'; import { LockedIcon, VisibleIcon } from '@parity/ui/Icons';
import DappsVisible from '../DappsVisible'; import DappsVisible from '../DappsVisible';
import DappPermissions from '../DappPermissions'; import DappAccounts from '../DappAccounts';
import PermissionStore from '../DappPermissions/store'; import PermissionStore from '../DappAccounts/store';
import DappsStore from './dappsStore'; import DappsStore from './dappsStore';
@ -80,7 +80,7 @@ class Dapps extends Component {
return ( return (
<div> <div>
<DappPermissions permissionStore={ this.permissionStore } /> <DappAccounts permissionStore={ this.permissionStore } />
<DappsVisible store={ this.store } /> <DappsVisible store={ this.store } />
<Actionbar <Actionbar
className={ styles.toolbar } className={ styles.toolbar }
@ -104,11 +104,11 @@ class Dapps extends Component {
/>, />,
<Button <Button
icon={ <LockedIcon /> } icon={ <LockedIcon /> }
key='permissions' key='accounts'
label={ label={
<FormattedMessage <FormattedMessage
id='dapps.button.permissions' id='dapps.button.accounts'
defaultMessage='permissions' defaultMessage='visible accounts'
/> />
} }
onClick={ this.openPermissionsModal } onClick={ this.openPermissionsModal }

View File

@ -41,7 +41,7 @@ import SecureApi from '~/secureApi';
import Application from './Application'; import Application from './Application';
import Dapp from './Dapp'; import Dapp from './Dapp';
import DappFilter from './DappFilter'; import { Store as DappFilterStore } from './DappFilter';
import Dapps from './Dapps'; import Dapps from './Dapps';
injectTapEventPlugin(); injectTapEventPlugin();
@ -67,10 +67,11 @@ const api = new SecureApi(uiUrl, token);
patchApi(api); patchApi(api);
ContractInstances.get(api); ContractInstances.get(api);
DappFilter.create(api.provider, { DappFilterStore.create(api.provider, {
filtered: [], filtered: [
tokens: { 'parity_hashContent'
} ],
tokens: {}
}); });
const store = initStore(api, hashHistory); const store = initStore(api, hashHistory);

View File

@ -28,8 +28,5 @@
<div class="loading">Loading</div> <div class="loading">Loading</div>
</div> </div>
<script src="vendor.js"></script> <script src="vendor.js"></script>
<% if (!htmlWebpackPlugin.options.secure) { %>
<script src="/parity-utils/parity.js"></script>
<% } %>
</body> </body>
</html> </html>