Method intercept dialog selection (#5875)
* Cleanup filter config * Show single request of type (at a time) * Align packages * DappFilter -> DappRequests * Methods dialog (WIP) * Initial dapp methods modal * Align dialog & popup permissions * appname -> token mapping TODOs * Case
This commit is contained in:
parent
d4532fac18
commit
e479260e1f
13
js/package-lock.json
generated
13
js/package-lock.json
generated
@ -28,13 +28,7 @@
|
|||||||
"version": "file:src/shell"
|
"version": "file:src/shell"
|
||||||
},
|
},
|
||||||
"@parity/ui": {
|
"@parity/ui": {
|
||||||
"version": "file:src/ui",
|
"version": "file:src/ui"
|
||||||
"dependencies": {
|
|
||||||
"react-event-listener": {
|
|
||||||
"version": "0.4.1",
|
|
||||||
"bundled": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"@parity/views": {
|
"@parity/views": {
|
||||||
"version": "file:src/views"
|
"version": "file:src/views"
|
||||||
@ -7300,11 +7294,6 @@
|
|||||||
"integrity": "sha1-EQvc9cRZxPd8uF7WNLzTOXU2ODs=",
|
"integrity": "sha1-EQvc9cRZxPd8uF7WNLzTOXU2ODs=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"react-addons-shallow-compare": {
|
|
||||||
"version": "15.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-addons-shallow-compare/-/react-addons-shallow-compare-15.6.0.tgz",
|
|
||||||
"integrity": "sha1-t6Tl/58nBMIM9obdigXdCLJt4lI="
|
|
||||||
},
|
|
||||||
"react-addons-test-utils": {
|
"react-addons-test-utils": {
|
||||||
"version": "15.4.2",
|
"version": "15.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-addons-test-utils/-/react-addons-test-utils-15.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-addons-test-utils/-/react-addons-test-utils-15.4.2.tgz",
|
||||||
|
@ -22,7 +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 DappRequests from '../DappRequests';
|
||||||
import Extension from '../Extension';
|
import Extension from '../Extension';
|
||||||
import FirstRun from '../FirstRun';
|
import FirstRun from '../FirstRun';
|
||||||
import ParityBar from '../ParityBar';
|
import ParityBar from '../ParityBar';
|
||||||
@ -83,7 +83,7 @@ class Application extends Component {
|
|||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
<Connection />
|
<Connection />
|
||||||
<DappFilter />
|
<DappRequests />
|
||||||
<Requests />
|
<Requests />
|
||||||
<ParityBar dapp={ isMinimized } />
|
<ParityBar dapp={ isMinimized } />
|
||||||
</div>
|
</div>
|
||||||
|
@ -14,5 +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 Store from './store';
|
export default from './methodCheck';
|
||||||
export default from './dappFilter';
|
|
40
js/src/shell/DappMethods/MethodCheck/methodCheck.js
Normal file
40
js/src/shell/DappMethods/MethodCheck/methodCheck.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// 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 { CheckboxTickedIcon, CheckboxUntickedIcon } from '@parity/ui/Icons';
|
||||||
|
|
||||||
|
export default function MethodCheck ({ checked, dappId, method, onToggle }) {
|
||||||
|
const _onClick = () => onToggle(method, dappId);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div onClick={ _onClick }>
|
||||||
|
{
|
||||||
|
checked
|
||||||
|
? <CheckboxTickedIcon />
|
||||||
|
: <CheckboxUntickedIcon />
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodCheck.propTypes = {
|
||||||
|
checked: PropTypes.bool.isRequired,
|
||||||
|
dappId: PropTypes.string.isRequired,
|
||||||
|
method: PropTypes.string.isRequired,
|
||||||
|
onToggle: PropTypes.func.isRequired
|
||||||
|
};
|
47
js/src/shell/DappMethods/dappMethods.css
Normal file
47
js/src/shell/DappMethods/dappMethods.css
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$border: 1px solid #ccc;
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
td {
|
||||||
|
border-bottom: $border;
|
||||||
|
border-right: $border;
|
||||||
|
padding: 0.25em;
|
||||||
|
vertical-align: center;
|
||||||
|
|
||||||
|
&.check {
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
height: 140px;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
transform: translate(25px, 51px) rotate(315deg);
|
||||||
|
width: 30px;
|
||||||
|
|
||||||
|
> span {
|
||||||
|
border-bottom: $border;
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
95
js/src/shell/DappMethods/dappMethods.js
Normal file
95
js/src/shell/DappMethods/dappMethods.js
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
// 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 { Portal } from '@parity/ui';
|
||||||
|
|
||||||
|
import MethodCheck from './MethodCheck';
|
||||||
|
import styles from './dappMethods.css';
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export default class DappsMethods extends Component {
|
||||||
|
static propTypes = {
|
||||||
|
methodsStore: PropTypes.object.isRequired,
|
||||||
|
visibleStore: PropTypes.object.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { methodsStore, visibleStore } = this.props;
|
||||||
|
|
||||||
|
if (!methodsStore.modalOpen) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Portal
|
||||||
|
className={ styles.modal }
|
||||||
|
onClose={ methodsStore.closeModal }
|
||||||
|
open
|
||||||
|
title={
|
||||||
|
<FormattedMessage
|
||||||
|
id='dapps.methods.label'
|
||||||
|
defaultMessage='allowed methods'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th> </th>
|
||||||
|
{
|
||||||
|
methodsStore.filteredRequests.map((method, requestIndex) => (
|
||||||
|
<th key={ requestIndex }>
|
||||||
|
<div>
|
||||||
|
<span>{ method }</span>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{
|
||||||
|
visibleStore.visibleApps.map(({ id, name }, dappIndex) => (
|
||||||
|
<tr key={ dappIndex }>
|
||||||
|
<td>{ name }</td>
|
||||||
|
{
|
||||||
|
methodsStore.filteredRequests.map((method, requestIndex) => (
|
||||||
|
<td
|
||||||
|
className={ styles.check }
|
||||||
|
key={ `${dappIndex}_${requestIndex}` }
|
||||||
|
>
|
||||||
|
<MethodCheck
|
||||||
|
checked={ methodsStore.permissions[`${method}:${id}`] || false }
|
||||||
|
dappId={ id }
|
||||||
|
method={ method }
|
||||||
|
onToggle={ methodsStore.toggleMethodPermission }
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</Portal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
17
js/src/shell/DappMethods/index.js
Normal file
17
js/src/shell/DappMethods/index.js
Normal 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 './dappMethods';
|
59
js/src/shell/DappMethods/store.js
Normal file
59
js/src/shell/DappMethods/store.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// 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, observable } from 'mobx';
|
||||||
|
|
||||||
|
import filteredRequests from '../DappRequests/filteredRequests';
|
||||||
|
|
||||||
|
export default class Store {
|
||||||
|
@observable filteredRequests = Object.keys(filteredRequests);
|
||||||
|
@observable modalOpen = false;
|
||||||
|
@observable permissions = {};
|
||||||
|
|
||||||
|
@action closeModal = () => {
|
||||||
|
this.modalOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action openModal = () => {
|
||||||
|
this.modalOpen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action addMethodPermission = (method, token) => {
|
||||||
|
const id = `${method}:${token}`;
|
||||||
|
|
||||||
|
this.permissions = Object.assign({}, this.permissions, {
|
||||||
|
[id]: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@action toggleMethodPermission = (method, token) => {
|
||||||
|
const id = `${method}:${token}`;
|
||||||
|
|
||||||
|
this.permissions = Object.assign({}, this.permissions, {
|
||||||
|
[id]: !this.permissions[id]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static instance = null;
|
||||||
|
|
||||||
|
static get () {
|
||||||
|
if (!Store.instance) {
|
||||||
|
Store.instance = new Store();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Store.instance;
|
||||||
|
}
|
||||||
|
}
|
@ -27,8 +27,8 @@ export default function Request ({ className, approveRequest, denyRequest, queue
|
|||||||
return (
|
return (
|
||||||
<div className={ className }>
|
<div className={ className }>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='dappFilter.request.info'
|
id='dappRequests.request.info'
|
||||||
defaultMessage='Received request from {method} from {from}'
|
defaultMessage='Received request for {method} from {from}'
|
||||||
values={ {
|
values={ {
|
||||||
from,
|
from,
|
||||||
method
|
method
|
||||||
@ -37,7 +37,7 @@ export default function Request ({ className, approveRequest, denyRequest, queue
|
|||||||
<Button
|
<Button
|
||||||
label={
|
label={
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='dappFilter.request.buttons.approve'
|
id='dappRequests.request.buttons.approve'
|
||||||
defaultMessage='Approve'
|
defaultMessage='Approve'
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ export default function Request ({ className, approveRequest, denyRequest, queue
|
|||||||
<Button
|
<Button
|
||||||
label={
|
label={
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='dappFilter.request.buttons.approveAll'
|
id='dappRequests.request.buttons.approveAll'
|
||||||
defaultMessage='Approve All'
|
defaultMessage='Approve All'
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
@ -55,7 +55,7 @@ export default function Request ({ className, approveRequest, denyRequest, queue
|
|||||||
<Button
|
<Button
|
||||||
label={
|
label={
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='dappFilter.request.buttons.reject'
|
id='dappRequests.request.buttons.reject'
|
||||||
defaultMessage='Reject'
|
defaultMessage='Reject'
|
||||||
/>
|
/>
|
||||||
}
|
}
|
@ -15,7 +15,7 @@
|
|||||||
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.filter {
|
.requests {
|
||||||
background: #f80;
|
background: #f80;
|
||||||
color: white;
|
color: white;
|
||||||
bottom: 0;
|
bottom: 0;
|
@ -19,9 +19,9 @@ import React from 'react';
|
|||||||
|
|
||||||
import Request from './Request';
|
import Request from './Request';
|
||||||
import Store from './store';
|
import Store from './store';
|
||||||
import styles from './dappFilter.css';
|
import styles from './dappRequests.css';
|
||||||
|
|
||||||
function DappFilter () {
|
function DappRequests () {
|
||||||
const store = Store.get();
|
const store = Store.get();
|
||||||
|
|
||||||
if (!store || !store.hasRequests) {
|
if (!store || !store.hasRequests) {
|
||||||
@ -29,9 +29,9 @@ function DappFilter () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ styles.filter }>
|
<div className={ styles.requests }>
|
||||||
{
|
{
|
||||||
store.requests.map(({ queueId, request: { data } }) => (
|
store.squashedRequests.map(({ queueId, request: { data } }) => (
|
||||||
<Request
|
<Request
|
||||||
className={ styles.request }
|
className={ styles.request }
|
||||||
approveRequest={ store.approveRequest }
|
approveRequest={ store.approveRequest }
|
||||||
@ -46,4 +46,4 @@ function DappFilter () {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default observer(DappFilter);
|
export default observer(DappRequests);
|
19
js/src/shell/DappRequests/filteredRequests.js
Normal file
19
js/src/shell/DappRequests/filteredRequests.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// 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 {
|
||||||
|
'parity_hashContent': {}
|
||||||
|
};
|
23
js/src/shell/DappRequests/index.js
Normal file
23
js/src/shell/DappRequests/index.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// 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 Store from './store';
|
||||||
|
|
||||||
|
export function setupProviderFilters (provider) {
|
||||||
|
return Store.create(provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default from './dappRequests';
|
@ -16,14 +16,16 @@
|
|||||||
|
|
||||||
import { action, computed, observable } from 'mobx';
|
import { action, computed, observable } from 'mobx';
|
||||||
|
|
||||||
|
import filteredRequests from './filteredRequests';
|
||||||
|
import MethodsStore from '../DappMethods/store';
|
||||||
|
|
||||||
let nextQueueId = 0;
|
let nextQueueId = 0;
|
||||||
|
|
||||||
export default class Store {
|
export default class Store {
|
||||||
@observable permissions = [];
|
@observable methodsStore = MethodsStore.get();
|
||||||
@observable requests = [];
|
@observable requests = [];
|
||||||
|
|
||||||
constructor (provider, permissions) {
|
constructor (provider) {
|
||||||
this.permissions = permissions;
|
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
|
|
||||||
window.addEventListener('message', this.receiveMessage, false);
|
window.addEventListener('message', this.receiveMessage, false);
|
||||||
@ -33,6 +35,21 @@ export default class Store {
|
|||||||
return this.requests.length !== 0;
|
return this.requests.length !== 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@computed get squashedRequests () {
|
||||||
|
const duplicates = {};
|
||||||
|
|
||||||
|
return this.requests.filter(({ request: { data: { method, token } } }) => {
|
||||||
|
const id = `${token}:${method}`;
|
||||||
|
|
||||||
|
if (!duplicates[id]) {
|
||||||
|
duplicates[id] = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@action removeRequest = (_queueId) => {
|
@action removeRequest = (_queueId) => {
|
||||||
this.requests = this.requests.filter(({ queueId }) => queueId !== _queueId);
|
this.requests = this.requests.filter(({ queueId }) => queueId !== _queueId);
|
||||||
}
|
}
|
||||||
@ -55,7 +72,8 @@ export default class Store {
|
|||||||
const { request: { data: { method, token } } } = queued;
|
const { request: { data: { method, token } } } = queued;
|
||||||
const requests = this.findMatchingRequests(method, token);
|
const requests = this.findMatchingRequests(method, token);
|
||||||
|
|
||||||
this.addTokenPermission(method, token);
|
// TODO: Use single-use token, map back to app name
|
||||||
|
this.methodsStore.addMethodPermission(method, token);
|
||||||
requests.forEach(this.approveSingleRequest);
|
requests.forEach(this.approveSingleRequest);
|
||||||
} else {
|
} else {
|
||||||
this.approveSingleRequest(queued);
|
this.approveSingleRequest(queued);
|
||||||
@ -75,14 +93,6 @@ export default class Store {
|
|||||||
}, '*');
|
}, '*');
|
||||||
}
|
}
|
||||||
|
|
||||||
@action addTokenPermission = (method, token) => {
|
|
||||||
this.permissions.tokens[token] = Object.assign({ [method]: true }, this.permissions.tokens[token] || {});
|
|
||||||
}
|
|
||||||
|
|
||||||
@action setPermissions = (permissions) => {
|
|
||||||
this.permissions = permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
findRequest (_queueId) {
|
findRequest (_queueId) {
|
||||||
return this.requests.find(({ queueId }) => queueId === _queueId);
|
return this.requests.find(({ queueId }) => queueId === _queueId);
|
||||||
}
|
}
|
||||||
@ -112,20 +122,25 @@ export default class Store {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.permissions.filtered.includes(method)) {
|
const filterId = `${method}:${token}`;
|
||||||
if (!this.permissions.tokens[token] || !this.permissions.tokens[token][method]) {
|
|
||||||
|
// TODO: Use single-use token, map back to app name
|
||||||
|
if (filteredRequests[method] && !this.methodsStore.permissions[filterId]) {
|
||||||
this.queueRequest({ data, origin, source });
|
this.queueRequest({ data, origin, source });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
this.executeOnProvider(data, source);
|
this.executeOnProvider(data, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
static instance = null;
|
static instance = null;
|
||||||
|
|
||||||
static create (provider, permissions) {
|
static create (provider) {
|
||||||
Store.instance = new Store(provider, permissions);
|
if (!Store.instance) {
|
||||||
|
Store.instance = new Store(provider, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Store.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get () {
|
static get () {
|
@ -21,11 +21,13 @@ import { FormattedMessage } from 'react-intl';
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { Actionbar, Button, Checkbox, DappCard, Page, SectionList } from '@parity/ui';
|
import { Actionbar, Button, Checkbox, DappCard, Page, SectionList } from '@parity/ui';
|
||||||
import { LockedIcon, VisibleIcon } from '@parity/ui/Icons';
|
import { LockedIcon, MethodsIcon, VisibleIcon } from '@parity/ui/Icons';
|
||||||
|
|
||||||
import DappsVisible from '../DappsVisible';
|
|
||||||
import DappAccounts from '../DappAccounts';
|
import DappAccounts from '../DappAccounts';
|
||||||
import PermissionStore from '../DappAccounts/store';
|
import PermissionStore from '../DappAccounts/store';
|
||||||
|
import DappMethods from '../DappMethods';
|
||||||
|
import MethodsStore from '../DappMethods/store';
|
||||||
|
import DappsVisible from '../DappsVisible';
|
||||||
|
|
||||||
import DappsStore from './dappsStore';
|
import DappsStore from './dappsStore';
|
||||||
|
|
||||||
@ -43,6 +45,7 @@ class Dapps extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
store = DappsStore.get(this.context.api);
|
store = DappsStore.get(this.context.api);
|
||||||
|
methodsStore = MethodsStore.get();
|
||||||
permissionStore = new PermissionStore(this.context.api);
|
permissionStore = new PermissionStore(this.context.api);
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
@ -81,6 +84,10 @@ class Dapps extends Component {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<DappAccounts permissionStore={ this.permissionStore } />
|
<DappAccounts permissionStore={ this.permissionStore } />
|
||||||
|
<DappMethods
|
||||||
|
methodsStore={ this.methodsStore }
|
||||||
|
visibleStore={ this.store }
|
||||||
|
/>
|
||||||
<DappsVisible store={ this.store } />
|
<DappsVisible store={ this.store } />
|
||||||
<Actionbar
|
<Actionbar
|
||||||
className={ styles.toolbar }
|
className={ styles.toolbar }
|
||||||
@ -97,7 +104,7 @@ class Dapps extends Component {
|
|||||||
label={
|
label={
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='dapps.button.edit'
|
id='dapps.button.edit'
|
||||||
defaultMessage='edit'
|
defaultMessage='edit applications'
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
onClick={ this.store.openModal }
|
onClick={ this.store.openModal }
|
||||||
@ -108,10 +115,21 @@ class Dapps extends Component {
|
|||||||
label={
|
label={
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='dapps.button.accounts'
|
id='dapps.button.accounts'
|
||||||
defaultMessage='visible accounts'
|
defaultMessage='allowed accounts'
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
onClick={ this.openPermissionsModal }
|
onClick={ this.openPermissionsModal }
|
||||||
|
/>,
|
||||||
|
<Button
|
||||||
|
icon={ <MethodsIcon /> }
|
||||||
|
key='methods'
|
||||||
|
label={
|
||||||
|
<FormattedMessage
|
||||||
|
id='dapps.button.methods'
|
||||||
|
defaultMessage='allowed methods'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
onClick={ this.methodsStore.openModal }
|
||||||
/>
|
/>
|
||||||
] }
|
] }
|
||||||
/>
|
/>
|
||||||
|
@ -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 { Store as DappFilterStore } from './DappFilter';
|
import { setupProviderFilters } from './DappRequests';
|
||||||
import Dapps from './Dapps';
|
import Dapps from './Dapps';
|
||||||
|
|
||||||
injectTapEventPlugin();
|
injectTapEventPlugin();
|
||||||
@ -67,12 +67,7 @@ const api = new SecureApi(uiUrl, token);
|
|||||||
patchApi(api);
|
patchApi(api);
|
||||||
ContractInstances.get(api);
|
ContractInstances.get(api);
|
||||||
|
|
||||||
DappFilterStore.create(api.provider, {
|
setupProviderFilters(api.provider);
|
||||||
filtered: [
|
|
||||||
'parity_hashContent'
|
|
||||||
],
|
|
||||||
tokens: {}
|
|
||||||
});
|
|
||||||
|
|
||||||
const store = initStore(api, hashHistory);
|
const store = initStore(api, hashHistory);
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ export const AttachFileIcon = (props) => <Icon name='attach' { ...props } />;
|
|||||||
export const BackgroundIcon = (props) => <Icon name='image' { ...props } />;
|
export const BackgroundIcon = (props) => <Icon name='image' { ...props } />;
|
||||||
export const CancelIcon = (props) => <Icon name='cancel' { ...props } />;
|
export const CancelIcon = (props) => <Icon name='cancel' { ...props } />;
|
||||||
export const CheckIcon = (props) => <Icon name='check' { ...props } />;
|
export const CheckIcon = (props) => <Icon name='check' { ...props } />;
|
||||||
|
export const CheckboxTickedIcon = (props) => <Icon name='check circle outline' { ...props } />;
|
||||||
|
export const CheckboxUntickedIcon = (props) => <Icon name='radio' { ...props } />;
|
||||||
export const CloseIcon = (props) => <Icon name='close' { ...props } />;
|
export const CloseIcon = (props) => <Icon name='close' { ...props } />;
|
||||||
export const CompareIcon = (props) => <Icon name='exchange' { ...props } />;
|
export const CompareIcon = (props) => <Icon name='exchange' { ...props } />;
|
||||||
export const ComputerIcon = (props) => <Icon name='desktop' { ...props } />;
|
export const ComputerIcon = (props) => <Icon name='desktop' { ...props } />;
|
||||||
@ -51,6 +53,7 @@ export const LinkIcon = (props) => <Icon name='linkify' { ...props } />;
|
|||||||
export const ListIcon = (props) => <Icon name='list ul' { ...props } />;
|
export const ListIcon = (props) => <Icon name='list ul' { ...props } />;
|
||||||
export const LockedIcon = (props) => <Icon name='unlock alternate' { ...props } />;
|
export const LockedIcon = (props) => <Icon name='unlock alternate' { ...props } />;
|
||||||
export const MembershipIcon = (props) => <Icon name='id card outline' { ...props } />;
|
export const MembershipIcon = (props) => <Icon name='id card outline' { ...props } />;
|
||||||
|
export const MethodsIcon = (props) => <Icon name='map signs' { ...props } />;
|
||||||
export const MoveIcon = (props) => <Icon name='move' { ...props } />;
|
export const MoveIcon = (props) => <Icon name='move' { ...props } />;
|
||||||
export const NextIcon = (props) => <Icon name='chevron right' { ...props } />;
|
export const NextIcon = (props) => <Icon name='chevron right' { ...props } />;
|
||||||
export const PauseIcon = (props) => <Icon name='pause' { ...props } />;
|
export const PauseIcon = (props) => <Icon name='pause' { ...props } />;
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
"react-copy-to-clipboard": "4.2.3",
|
"react-copy-to-clipboard": "4.2.3",
|
||||||
"react-datetime": "2.8.10",
|
"react-datetime": "2.8.10",
|
||||||
"react-dropzone": "3.7.3",
|
"react-dropzone": "3.7.3",
|
||||||
"react-event-listener": "0.4.1",
|
"react-event-listener": "^0.4.0",
|
||||||
"react-portal": "3.0.0",
|
"react-portal": "3.0.0",
|
||||||
"react-qr-reader": "1.0.3",
|
"react-qr-reader": "1.0.3",
|
||||||
"recharts": "0.15.2",
|
"recharts": "0.15.2",
|
||||||
|
Loading…
Reference in New Issue
Block a user