Fix/Update method permissions (#7233)
* Use hex everywhere as appId * Extract requestGroup sub item from clarity * Change size of icon in SignerPending
This commit is contained in:
committed by
Jaco Greeff
parent
3cb4d81eb1
commit
f6f7a87dc6
@@ -6,4 +6,16 @@ To be clear with the terminology used in the code here:
|
||||
- a *methodGroup* is the grouping of similar methods (see `methodGroups.js`)
|
||||
- a *permission* is a boolean which tells if an app is allowed to call a method or not
|
||||
- a *request* is when an app prompts the shell to call a method
|
||||
- a *requestGroup* is an array of *requests* whose methods are in the same *methodGroup*
|
||||
- a *requestGroup* is a map of the following form
|
||||
```javascript
|
||||
{
|
||||
appId1: {
|
||||
methodGroup1: [request1, request2] // This is a requestGroup sub-item
|
||||
},
|
||||
appId2: {
|
||||
methodGroup1: [request1]
|
||||
methodGroup2: [request3]
|
||||
},
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
.requestGroupSubItem {
|
||||
margin-top: 2px;
|
||||
|
||||
.requestGroupSubItemTitle {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// 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, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import Popup from 'semantic-ui-react/dist/commonjs/modules/Popup';
|
||||
import Button from '@parity/ui/lib/Button';
|
||||
|
||||
import methodGroups from '../../methodGroups';
|
||||
import styles from './RequestGroupSubItem.css';
|
||||
|
||||
export default class RequestGroupSubItem extends PureComponent {
|
||||
handleApprove = () => this.props.onApprove(this.props.requests, this.props.groupId)
|
||||
|
||||
handleReject = () => this.props.onReject(this.props.requests)
|
||||
|
||||
render () {
|
||||
const { groupId } = this.props;
|
||||
|
||||
return (
|
||||
<div className={ styles.requestGroupSubItem }>
|
||||
<span className={ styles.requestGroupSubItemTitle }>
|
||||
Permission for{' '}
|
||||
<Popup
|
||||
trigger={ <span>{groupId}</span> }
|
||||
content={ `Requested methods: ${methodGroups[groupId].methods.join(', ')}` }
|
||||
/>
|
||||
</span>
|
||||
<Button
|
||||
size='mini'
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='dappRequests.request.buttons.approve'
|
||||
defaultMessage='Approve'
|
||||
/>
|
||||
}
|
||||
onClick={ this.handleApprove }
|
||||
/>
|
||||
<Button
|
||||
size='mini'
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='dappRequests.request.buttons.reject'
|
||||
defaultMessage='Reject'
|
||||
/>
|
||||
}
|
||||
onClick={ this.handleReject }
|
||||
/>
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
RequestGroupSubItem.propTypes = {
|
||||
className: PropTypes.string,
|
||||
groupId: PropTypes.string,
|
||||
onApprove: PropTypes.func.isRequired,
|
||||
onReject: PropTypes.func.isRequired,
|
||||
requests: PropTypes.array.isRequired
|
||||
};
|
||||
@@ -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 './RequestGroupSubItem';
|
||||
@@ -28,12 +28,4 @@ $backgroundTwo: #e57a00;
|
||||
> span {
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.requestGroup {
|
||||
margin-top: 2px;
|
||||
|
||||
.requestGroupTitle {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,49 +14,25 @@
|
||||
// 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, { PureComponent } from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import Popup from 'semantic-ui-react/dist/commonjs/modules/Popup';
|
||||
import Button from '@parity/ui/lib/Button';
|
||||
|
||||
import DappsStore from '@parity/shared/lib/mobx/dappsStore';
|
||||
|
||||
import RequestGroupSubItem from './RequestGroupSubItem';
|
||||
import styles from './RequestGroups.css';
|
||||
|
||||
export default class RequestGroups extends PureComponent {
|
||||
state = {
|
||||
opened: false
|
||||
};
|
||||
|
||||
handleApproveRequestGroup = groupId => {
|
||||
const { requestGroups, onApproveRequestGroup } = this.props;
|
||||
|
||||
onApproveRequestGroup(Object.values(requestGroups[groupId].map(({ requestId }) => requestId)));
|
||||
}
|
||||
|
||||
handleRejectRequestGroup = groupId => {
|
||||
const { requestGroups, onRejectRequestGroup } = this.props;
|
||||
|
||||
onRejectRequestGroup(Object.values(requestGroups[groupId].map(({ requestId }) => requestId)));
|
||||
}
|
||||
|
||||
renderPopupContent = groupId => {
|
||||
const { requestGroups } = this.props;
|
||||
// Get unique list of methods in that request group
|
||||
const requestedMethods = [...new Set(
|
||||
Object.values(requestGroups[groupId])
|
||||
.map(request => request.data.method || request.data.params[0])
|
||||
)];
|
||||
|
||||
return `Requested methods: ${requestedMethods.join(', ')}`;
|
||||
export default class RequestGroups extends Component {
|
||||
handleApproveRequestGroup = (requests, groupId) => {
|
||||
this.props.onApproveRequestGroup(requests, groupId, this.props.appId);
|
||||
}
|
||||
|
||||
render () {
|
||||
const {
|
||||
appId,
|
||||
requestGroups
|
||||
requestGroups,
|
||||
onRejectRequestGroup
|
||||
} = this.props;
|
||||
|
||||
const app = DappsStore.get().getAppById(appId);
|
||||
@@ -72,35 +48,13 @@ export default class RequestGroups extends PureComponent {
|
||||
} }
|
||||
/>
|
||||
{Object.keys(requestGroups).map(groupId => (
|
||||
<div key={ `${appId}-${groupId}` } className={ styles.requestGroup }>
|
||||
<span className={ styles.requestGroupTitle }>
|
||||
Permission for{' '}
|
||||
<Popup
|
||||
trigger={ <span>{groupId}</span> }
|
||||
content={ this.renderPopupContent(groupId) }
|
||||
/>
|
||||
</span>
|
||||
<Button
|
||||
size='mini'
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='dappRequests.request.buttons.approve'
|
||||
defaultMessage='Approve'
|
||||
/>
|
||||
}
|
||||
onClick={ () => this.handleApproveRequestGroup(groupId) }
|
||||
/>
|
||||
<Button
|
||||
size='mini'
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='dappRequests.request.buttons.reject'
|
||||
defaultMessage='Reject'
|
||||
/>
|
||||
}
|
||||
onClick={ () => this.handleRejectRequestGroup(groupId) }
|
||||
/>
|
||||
</div>
|
||||
<RequestGroupSubItem
|
||||
key={ `${appId}-${groupId}` }
|
||||
groupId={ groupId }
|
||||
requests={ requestGroups[groupId] }
|
||||
onApprove={ this.handleApproveRequestGroup }
|
||||
onReject={ onRejectRequestGroup }
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
import { observer } from 'mobx-react';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import methodGroups from './methodGroups';
|
||||
import RequestGroups from './RequestGroups';
|
||||
import Store from './store';
|
||||
import styles from './dappRequests.css';
|
||||
@@ -24,12 +25,16 @@ import styles from './dappRequests.css';
|
||||
class DappRequests extends Component {
|
||||
store = Store.get();
|
||||
|
||||
handleApproveRequestGroup = requestIds => {
|
||||
requestIds.forEach(this.store.approveRequest);
|
||||
// When we approve a requestGroup, when approve all the requests, and add permissions
|
||||
// to all the other methods in the same methodGroup
|
||||
handleApproveRequestGroup = (requests, groupId, appId) => {
|
||||
requests.map(({ requestId }) => requestId).forEach(this.store.approveRequest);
|
||||
methodGroups[groupId].methods.forEach(method => this.store.addAppPermission(method, appId));
|
||||
}
|
||||
|
||||
handleRejectRequestGroup = requestIds => {
|
||||
requestIds.forEach(this.store.rejectRequest);
|
||||
// When we reject a requestGroup, we reject the requests in that group
|
||||
handleRejectRequestGroup = requests => {
|
||||
requests.map(({ requestId }) => requestId).forEach(this.store.rejectRequest);
|
||||
}
|
||||
|
||||
render () {
|
||||
|
||||
@@ -18,6 +18,7 @@ import { action, computed, observable } from 'mobx';
|
||||
import store from 'store';
|
||||
|
||||
import { sha3 } from '@parity/api/lib/util/sha3';
|
||||
import { isHex } from '@parity/api/lib/util/types';
|
||||
|
||||
import { methodGroupFromMethod } from './methodGroups';
|
||||
|
||||
@@ -52,7 +53,7 @@ export default class Store {
|
||||
|
||||
accumulator[appId] = accumulator[appId] || {};
|
||||
accumulator[appId][methodGroup] = accumulator[appId][methodGroup] || [];
|
||||
accumulator[appId][methodGroup].push({ data, requestId }); // Append the requestId field in the request object
|
||||
accumulator[appId][methodGroup].push({ data, requestId }); // Push request & append the requestId field in the request object
|
||||
|
||||
return accumulator;
|
||||
}, {});
|
||||
@@ -99,7 +100,7 @@ export default class Store {
|
||||
this.requests = { ...this.requests };
|
||||
};
|
||||
|
||||
getPermissionId = (method, appId) => `${method}:${appId}` // Create an id to identify permissions based on method and appId
|
||||
getPermissionId = (method, appId) => `${method}:${isHex(appId) ? appId : sha3(appId)}`; // Create an id to identify permissions based on method and appId
|
||||
|
||||
getMethodFromRequest = requestId => {
|
||||
const { data: { method, params } } = this.requests[requestId];
|
||||
@@ -131,13 +132,10 @@ export default class Store {
|
||||
};
|
||||
|
||||
setPermissions = _permissions => {
|
||||
const permissions = {};
|
||||
|
||||
Object.keys(_permissions).forEach(id => {
|
||||
permissions[id] = !!_permissions[id];
|
||||
});
|
||||
|
||||
this.permissions = permissions;
|
||||
this.permissions = {
|
||||
...this.permissions,
|
||||
..._permissions
|
||||
};
|
||||
this.savePermissions();
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user