diff --git a/js/package-lock.json b/js/package-lock.json index 435030388..a22f5eefb 100644 --- a/js/package-lock.json +++ b/js/package-lock.json @@ -53,7 +53,7 @@ "dev": true, "requires": { "@parity/api": "2.1.5", - "@parity/shared": "2.2.8", + "@parity/shared": "2.2.9", "@parity/ui": "2.2.15", "lodash": "4.17.4", "mobx": "3.3.2", @@ -76,7 +76,7 @@ "requires": { "@parity/api": "2.1.5", "@parity/etherscan": "2.1.3", - "@parity/shared": "2.2.8", + "@parity/shared": "2.2.9", "bignumber.js": "3.0.1", "brace": "0.9.0", "date-difference": "1.0.0", @@ -578,7 +578,7 @@ "requires": { "@parity/api": "2.1.5", "@parity/etherscan": "2.1.3", - "@parity/shared": "2.2.8", + "@parity/shared": "2.2.9", "bignumber.js": "3.0.1", "brace": "0.9.0", "date-difference": "1.0.0", @@ -1151,9 +1151,9 @@ "version": "github:paritytech/plugin-signer-qr#c16423de5b8a8f68ebd5f1e78e084fa959329a9f" }, "@parity/shared": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/@parity/shared/-/shared-2.2.8.tgz", - "integrity": "sha512-gSF4rX2dsjEHAlWvCSNRPeWRSGBKLxev6ke6othzmO4AluTK71A4ZM3N18fw5NTybCiiELbdNUPkxzCtvs92Ew==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@parity/shared/-/shared-2.2.9.tgz", + "integrity": "sha512-bbzfcFNt0XsO9oJj3ySPfMgFAcPtFJElHbEXTm4xU4xntADoSIYuWtvonq2uULxA1LQ1O+1hGpyagQ8OZ+YoqQ==", "requires": { "@parity/ledger": "2.1.2", "eventemitter3": "2.0.3", @@ -1215,7 +1215,7 @@ "requires": { "@parity/api": "2.1.5", "@parity/etherscan": "2.1.3", - "@parity/shared": "2.2.8", + "@parity/shared": "2.2.9", "babel-runtime": "6.26.0", "bignumber.js": "4.1.0", "brace": "0.11.0", @@ -2371,7 +2371,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.1.tgz", "integrity": "sha1-0+MQtA72ZKNmIiAAl8bUQCmPK/4=", - "dev": true, "requires": { "babel-plugin-transform-strict-mode": "6.24.1", "babel-runtime": "6.26.0", @@ -2709,7 +2708,7 @@ "babel-plugin-transform-es2015-function-name": "6.24.1", "babel-plugin-transform-es2015-literals": "6.22.0", "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-modules-commonjs": "6.24.1", "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", "babel-plugin-transform-es2015-modules-umd": "6.24.1", "babel-plugin-transform-es2015-object-super": "6.24.1", @@ -2721,19 +2720,6 @@ "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", "babel-plugin-transform-es2015-unicode-regex": "6.24.1", "babel-plugin-transform-regenerator": "6.26.0" - }, - "dependencies": { - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", - "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", - "requires": { - "babel-plugin-transform-strict-mode": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-types": "6.26.0" - } - } } }, "babel-preset-flow": { diff --git a/js/package.json b/js/package.json index 5435843f8..0b788c98c 100644 --- a/js/package.json +++ b/js/package.json @@ -147,7 +147,7 @@ "@parity/plugin-signer-default": "paritytech/plugin-signer-default", "@parity/plugin-signer-hardware": "paritytech/plugin-signer-hardware", "@parity/plugin-signer-qr": "paritytech/plugin-signer-qr", - "@parity/shared": "^2.2.8", + "@parity/shared": "^2.2.9", "@parity/ui": "^3.0.14", "keythereum": "1.0.2", "lodash.flatten": "4.4.0", diff --git a/js/src/DappRequests/README.md b/js/src/DappRequests/README.md index f4ed60b40..84e838789 100644 --- a/js/src/DappRequests/README.md +++ b/js/src/DappRequests/README.md @@ -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] + }, + // ... +} +``` diff --git a/js/src/DappRequests/RequestGroups/RequestGroupSubItem/RequestGroupSubItem.css b/js/src/DappRequests/RequestGroups/RequestGroupSubItem/RequestGroupSubItem.css new file mode 100644 index 000000000..74837da45 --- /dev/null +++ b/js/src/DappRequests/RequestGroups/RequestGroupSubItem/RequestGroupSubItem.css @@ -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 . +*/ + +.requestGroupSubItem { + margin-top: 2px; + + .requestGroupSubItemTitle { + margin-right: 10px; + } +} diff --git a/js/src/DappRequests/RequestGroups/RequestGroupSubItem/RequestGroupSubItem.js b/js/src/DappRequests/RequestGroups/RequestGroupSubItem/RequestGroupSubItem.js new file mode 100644 index 000000000..1ed845a21 --- /dev/null +++ b/js/src/DappRequests/RequestGroups/RequestGroupSubItem/RequestGroupSubItem.js @@ -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 . + +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 ( +
+ + Permission for{' '} + {groupId} } + content={ `Requested methods: ${methodGroups[groupId].methods.join(', ')}` } + /> + +
+ + ); + } +} + +RequestGroupSubItem.propTypes = { + className: PropTypes.string, + groupId: PropTypes.string, + onApprove: PropTypes.func.isRequired, + onReject: PropTypes.func.isRequired, + requests: PropTypes.array.isRequired +}; diff --git a/js/src/DappRequests/RequestGroups/RequestGroupSubItem/index.js b/js/src/DappRequests/RequestGroups/RequestGroupSubItem/index.js new file mode 100644 index 000000000..475d0a0f4 --- /dev/null +++ b/js/src/DappRequests/RequestGroups/RequestGroupSubItem/index.js @@ -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 . + +export default from './RequestGroupSubItem'; diff --git a/js/src/DappRequests/RequestGroups/RequestGroups.css b/js/src/DappRequests/RequestGroups/RequestGroups.css index 65335e85e..7354c7870 100644 --- a/js/src/DappRequests/RequestGroups/RequestGroups.css +++ b/js/src/DappRequests/RequestGroups/RequestGroups.css @@ -28,12 +28,4 @@ $backgroundTwo: #e57a00; > span { margin-right: 30px; } - - .requestGroup { - margin-top: 2px; - - .requestGroupTitle { - margin-right: 10px; - } - } } diff --git a/js/src/DappRequests/RequestGroups/RequestGroups.js b/js/src/DappRequests/RequestGroups/RequestGroups.js index 42328ed2a..fd386370f 100644 --- a/js/src/DappRequests/RequestGroups/RequestGroups.js +++ b/js/src/DappRequests/RequestGroups/RequestGroups.js @@ -14,49 +14,25 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -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 => ( -
- - Permission for{' '} - {groupId} } - content={ this.renderPopupContent(groupId) } - /> - -
+ ))} ); diff --git a/js/src/DappRequests/dappRequests.js b/js/src/DappRequests/dappRequests.js index 275fbbb23..406e44078 100644 --- a/js/src/DappRequests/dappRequests.js +++ b/js/src/DappRequests/dappRequests.js @@ -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 () { diff --git a/js/src/DappRequests/store.js b/js/src/DappRequests/store.js index 5a89ad29a..6d3138e78 100644 --- a/js/src/DappRequests/store.js +++ b/js/src/DappRequests/store.js @@ -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; diff --git a/js/src/Dapps/dapps.css b/js/src/Dapps/dapps.css index 52b8ad408..02cfced8f 100644 --- a/js/src/Dapps/dapps.css +++ b/js/src/Dapps/dapps.css @@ -19,7 +19,6 @@ background: rgba(40, 40, 40, 0.85); color: white; line-height: 1.5em; - text-align: left; padding: 4em 2em; position: fixed; top: 0; diff --git a/js/src/Status/SignerPending/RequestItem/requestItem.css b/js/src/Status/SignerPending/RequestItem/requestItem.css index 5d1a2e9b6..7f4a9a121 100644 --- a/js/src/Status/SignerPending/RequestItem/requestItem.css +++ b/js/src/Status/SignerPending/RequestItem/requestItem.css @@ -19,6 +19,11 @@ display: flex !important; } +.fromAvatar { + width: 28px !important; + height: 28px !important; +} + .toAvatar { margin-left: 3px; } diff --git a/js/src/Status/SignerPending/RequestItem/requestItem.js b/js/src/Status/SignerPending/RequestItem/requestItem.js index 13cddea0f..f96bd7859 100644 --- a/js/src/Status/SignerPending/RequestItem/requestItem.js +++ b/js/src/Status/SignerPending/RequestItem/requestItem.js @@ -168,6 +168,7 @@ class RequestItem extends Component {