Skip to content
This repository has been archived by the owner on Jan 25, 2022. It is now read-only.

Commit

Permalink
basic wallet_enable and related methods
Browse files Browse the repository at this point in the history
  • Loading branch information
rekmarks committed Dec 11, 2019
1 parent 431d2ab commit a46baad
Show file tree
Hide file tree
Showing 12 changed files with 406 additions and 175 deletions.
14 changes: 13 additions & 1 deletion app/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
"clearPlugins": {
"message": "Clear Snaps"
},
"clearPluginsDescription": {
"message": "Remove all Snaps and their associated permissions."
},
"confirmClearPlugins": {
"message": "Are you sure you want to remove all Snaps and their associated permissions?"
},
Expand All @@ -56,6 +59,9 @@
"clearPermissions": {
"message": "Clear Permissions"
},
"clearPermissionsDescription": {
"message": "Clear permissions so that all dapps/websites must request access again."
},
"confirmClearPermissions": {
"message": "Are you sure you want to remove all dapp/website permissions?"
},
Expand All @@ -74,6 +80,9 @@
"clearPermissionsActivity": {
"message": "Clear Permissions Activity"
},
"clearPermissionsActivityDescription": {
"message": "Clear the permissions activity log."
},
"confirmClearPermissionsActivity": {
"message": "Are you sure you want to clear the permissions activity log?"
},
Expand All @@ -89,6 +98,9 @@
"clearPermissionsHistory": {
"message": "Clear Permissions History"
},
"clearPermissionsHistoryDescription": {
"message": "Clear the permissions history."
},
"confirmClearPermissionsHistory": {
"message": "Are you sure you want to clear the permissions history?"
},
Expand Down Expand Up @@ -1011,7 +1023,7 @@
"message": "Permissions"
},
"permissionsSettingsDescription": {
"message": "Manage dapp/website permissions."
"message": "Manage dapp/website permissions"
},
"personalAddressDetected": {
"message": "Personal address detected. Input the token contract address."
Expand Down
62 changes: 62 additions & 0 deletions app/scripts/controllers/permissions/enums.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
module.exports = {
WALLET_PREFIX: 'wallet_',
PLUGIN_PREFIX: 'wallet_plugin_',
HISTORY_STORE_KEY: 'permissionsHistory',
LOG_STORE_KEY: 'permissionsLog',
METADATA_STORE_KEY: 'domainMetadata',
CAVEAT_NAMES: {
exposedAccounts: 'exposedAccounts',
},
NOTIFICATION_NAMES: {
accountsChanged: 'wallet_accountsChanged',
},
SAFE_METHODS: [
'web3_sha3',
'net_listening',
'net_peerCount',
'net_version',
'eth_blockNumber',
'eth_call',
'eth_chainId',
'eth_coinbase',
'eth_estimateGas',
'eth_gasPrice',
'eth_getBalance',
'eth_getBlockByHash',
'eth_getBlockByNumber',
'eth_getBlockTransactionCountByHash',
'eth_getBlockTransactionCountByNumber',
'eth_getCode',
'eth_getFilterChanges',
'eth_getFilterLogs',
'eth_getLogs',
'eth_getStorageAt',
'eth_getTransactionByBlockHashAndIndex',
'eth_getTransactionByBlockNumberAndIndex',
'eth_getTransactionByHash',
'eth_getTransactionCount',
'eth_getTransactionReceipt',
'eth_getUncleByBlockHashAndIndex',
'eth_getUncleByBlockNumberAndIndex',
'eth_getUncleCountByBlockHash',
'eth_getUncleCountByBlockNumber',
'eth_getWork',
'eth_hashrate',
'eth_mining',
'eth_newBlockFilter',
'eth_newFilter',
'eth_newPendingTransactionFilter',
'eth_protocolVersion',
'eth_sendRawTransaction',
'eth_sendTransaction',
'eth_sign',
'personal_sign',
'eth_signTypedData',
'eth_signTypedData_v1',
'eth_signTypedData_v3',
'eth_submitHashrate',
'eth_submitWork',
'eth_syncing',
'eth_uninstallFilter',
],
}
94 changes: 50 additions & 44 deletions app/scripts/controllers/permissions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,19 @@ const {
const createMethodMiddleware = require('./methodMiddleware')
const createLoggerMiddleware = require('./loggerMiddleware')

// Methods that do not require any permissions to use:
const SAFE_METHODS = require('./permissions-safe-methods.json')

const METADATA_STORE_KEY = 'domainMetadata'
const LOG_STORE_KEY = 'permissionsLog'
const HISTORY_STORE_KEY = 'permissionsHistory'
const WALLET_METHOD_PREFIX = 'wallet_'
const CAVEAT_NAMES = {
exposedAccounts: 'exposedAccounts',
}
const ACCOUNTS_CHANGED_NOTIFICATION = 'wallet_accountsChanged'
const {
SAFE_METHODS, // methods that do not require any permissions to use
WALLET_PREFIX,
PLUGIN_PREFIX,
METADATA_STORE_KEY,
LOG_STORE_KEY,
HISTORY_STORE_KEY,
CAVEAT_NAMES,
NOTIFICATION_NAMES,
} = require('./enums')

function prefix (method) {
return WALLET_METHOD_PREFIX + method
return WALLET_PREFIX + method
}

class PermissionsController {
Expand All @@ -34,8 +33,7 @@ class PermissionsController {
openPopup, closePopup, keyringController, assetsController,
setupProvider, pluginRestrictedMethods, getApi, notifyDomain,
notifyAllDomains,
} = {},
restoredState = {}
} = {}, restoredState = {}
) {
this.store = new ObservableStore({
[METADATA_STORE_KEY]: restoredState[METADATA_STORE_KEY] || {},
Expand Down Expand Up @@ -71,13 +69,11 @@ class PermissionsController {
store: this.store,
storeKey: METADATA_STORE_KEY,
getAccounts: this.getAccounts.bind(this, origin),
requestAccountsPermission: this._requestPermissions.bind(
this, origin, { eth_accounts: {} }
),
handleInstallPlugins: this.handleInstallPlugins.bind(this),
requestPermissions: this._requestPermissions.bind(this, origin),
installPlugins: this.installPlugins.bind(this),
}))
engine.push(createLoggerMiddleware({
walletPrefix: WALLET_METHOD_PREFIX,
walletPrefix: WALLET_PREFIX,
restrictedMethods: (
Object.keys(this.externalRestrictedMethods)
.concat(Object.keys(this.pluginRestrictedMethods))
Expand Down Expand Up @@ -113,9 +109,9 @@ class PermissionsController {

/**
* @param {string} origin - The external domain id.
* @param {Array<string>} requestedPlugins - The names of the requested plugin permissions.
* @param {Object} requestedPlugins - The names of the requested plugin permissions.
*/
async handleInstallPlugins (origin, requestedPlugins) {
async installPlugins (origin, requestedPlugins) {

const existingPerms = this.permissions.getPermissionsForDomain(origin).reduce(
(acc, p) => {
Expand All @@ -124,24 +120,34 @@ class PermissionsController {
}, {}
)

requestedPlugins.forEach(p => {
if (!existingPerms[p]) {
throw ethErrors.provider.unauthorized(`Not authorized to install plugin '${p}'.`)
const result = {}

// use a for-loop so that we can return an object and await the resolution
// of each call to processRequestedPlugin
for (const pluginName of Object.keys(requestedPlugins)) {

const permissionName = PLUGIN_PREFIX + pluginName
result[pluginName] = {
permission: permissionName,
}
})

const installedPlugins = await this.pluginsController.processRequestedPlugins(requestedPlugins)
// only allow the installation of permitted plugins
if (!existingPerms[permissionName]) {

if (installedPlugins.length === 0) {
// TODO:plugins reserve error in Ethereum error space?
throw ethErrors.provider.custom({
code: 4301,
message: 'Failed to install all plugins.',
data: requestedPlugins,
})
}
result[pluginName].error = ethErrors.provider.unauthorized(
`Not authorized to install plugin '${pluginName}'. Please request the permission for the plugin before attempting to install it.`
)
} else {

return installedPlugins
// attempt to install and run the plugin, storing any errors that
// occur during the process
result[pluginName] = {
...result[pluginName],
...(await this.pluginsController.processRequestedPlugin(pluginName)),
}
}
}
return result
}

/**
Expand Down Expand Up @@ -298,7 +304,7 @@ class PermissionsController {
)

this.notifyDomain(origin, {
method: ACCOUNTS_CHANGED_NOTIFICATION,
method: NOTIFICATION_NAMES.accountsChanged,
result: accounts,
})
}
Expand Down Expand Up @@ -373,7 +379,7 @@ class PermissionsController {
if (methodName === 'eth_accounts') {
this.notifyDomain(
origin,
{ method: ACCOUNTS_CHANGED_NOTIFICATION, result: [] }
{ method: NOTIFICATION_NAMES.accountsChanged, result: [] }
)
}

Expand All @@ -392,7 +398,7 @@ class PermissionsController {
domainsToDelete.forEach(d => {
delete domains[d]
this.notifyDomain(d, {
method: ACCOUNTS_CHANGED_NOTIFICATION,
method: NOTIFICATION_NAMES.accountsChanged,
result: [],
})
})
Expand Down Expand Up @@ -428,7 +434,7 @@ class PermissionsController {
clearPermissions () {
this.permissions.clearDomains()
this.notifyAllDomains({
method: ACCOUNTS_CHANGED_NOTIFICATION,
method: NOTIFICATION_NAMES.accountsChanged,
result: [],
})
}
Expand Down Expand Up @@ -459,28 +465,28 @@ class PermissionsController {
* @param {Object} opts - The CapabilitiesController options.
* @param {Object} opts.metamaskEventMethods - Plugin-related internal event methods.
* @param {Object} opts.pluginRestrictedMethods - Restricted methods for plugins, if any.
* @param {Object} opts.restoredState - The restored state, if any.
* @param {Object} opts.restoredPermissions - The restored permissions state, if any.
*/
initializePermissions ({
pluginsController,
metamaskEventMethods = {},
pluginRestrictedMethods = {},
restoredState = {},
restoredPermissions = {},
} = {}) {

this.pluginsController = pluginsController
this.metamaskEventMethods = metamaskEventMethods
this.pluginRestrictedMethods = pluginRestrictedMethods

const initState = Object.keys(restoredState)
const initState = Object.keys(restoredPermissions)
.filter(k => {
return ![
'permissionsDescriptions',
'permissionsRequests',
].includes(k)
})
.reduce((acc, k) => {
acc[k] = restoredState[k]
acc[k] = restoredPermissions[k]
return acc
}, {})

Expand Down Expand Up @@ -518,7 +524,7 @@ class PermissionsController {
safeMethods: SAFE_METHODS,

// optional prefix for internal methods
methodPrefix: WALLET_METHOD_PREFIX,
methodPrefix: WALLET_PREFIX,

restrictedMethods: {
...this.externalRestrictedMethods, ...namespacedPluginRestrictedMethods,
Expand Down
Loading

0 comments on commit a46baad

Please sign in to comment.