diff --git a/app/scripts/lib/rpc-method-middleware/createMethodMiddleware.js b/app/scripts/lib/rpc-method-middleware/createMethodMiddleware.js index fa7798d0d..9c7935d3e 100644 --- a/app/scripts/lib/rpc-method-middleware/createMethodMiddleware.js +++ b/app/scripts/lib/rpc-method-middleware/createMethodMiddleware.js @@ -4,7 +4,7 @@ import handlers from './handlers'; const handlerMap = handlers.reduce((map, handler) => { for (const methodName of handler.methodNames) { - map.set(methodName, handler.implementation); + map.set(methodName, handler); } return map; }, new Map()); @@ -23,7 +23,6 @@ const handlerMap = handlers.reduce((map, handler) => { * Eventually, we'll want to extract this middleware into its own package. * * @param {Object} opts - The middleware options - * @param {Function} opts.sendMetrics - A function for sending a metrics event * @returns {(req: Object, res: Object, next: Function, end: Function) => void} */ export default function createMethodMiddleware(opts) { @@ -33,9 +32,32 @@ export default function createMethodMiddleware(opts) { return end(ethErrors.rpc.methodNotSupported()); } - if (handlerMap.has(req.method)) { - return handlerMap.get(req.method)(req, res, next, end, opts); + const handler = handlerMap.get(req.method); + if (handler) { + const { implementation, hookNames } = handler; + return implementation(req, res, next, end, selectHooks(opts, hookNames)); } + return next(); }; } + +/** + * Returns the subset of the specified `hooks` that are included in the + * `hookNames` object. This is a Principle of Least Authority (POLA) measure + * to ensure that each RPC method implementation only has access to the + * API "hooks" it needs to do its job. + * + * @param {Record} hooks - The hooks to select from. + * @param {Record} hookNames - The names of the hooks to select. + * @returns {Record | undefined} The selected hooks. + */ +function selectHooks(hooks, hookNames) { + if (hookNames) { + return Object.keys(hookNames).reduce((hookSubset, hookName) => { + hookSubset[hookName] = hooks[hookName]; + return hookSubset; + }, {}); + } + return undefined; +} diff --git a/app/scripts/lib/rpc-method-middleware/handlers/add-ethereum-chain.js b/app/scripts/lib/rpc-method-middleware/handlers/add-ethereum-chain.js index 50399c3ab..c6a85c2fb 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/add-ethereum-chain.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/add-ethereum-chain.js @@ -12,6 +12,14 @@ import { CHAIN_ID_TO_NETWORK_ID_MAP } from '../../../../../shared/constants/netw const addEthereumChain = { methodNames: [MESSAGE_TYPE.ADD_ETHEREUM_CHAIN], implementation: addEthereumChainHandler, + hookNames: { + addCustomRpc: true, + getCurrentChainId: true, + findCustomRpcBy: true, + updateRpcTarget: true, + requestUserApproval: true, + sendMetrics: true, + }, }; export default addEthereumChain; diff --git a/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.js b/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.js index c38933b0d..afc09666a 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.js @@ -9,6 +9,9 @@ import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; const getProviderState = { methodNames: [MESSAGE_TYPE.GET_PROVIDER_STATE], implementation: getProviderStateHandler, + hookNames: { + getProviderState: true, + }, }; export default getProviderState; diff --git a/app/scripts/lib/rpc-method-middleware/handlers/log-web3-shim-usage.js b/app/scripts/lib/rpc-method-middleware/handlers/log-web3-shim-usage.js index 973d03f61..8793cdf20 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/log-web3-shim-usage.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/log-web3-shim-usage.js @@ -10,6 +10,11 @@ import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; const logWeb3ShimUsage = { methodNames: [MESSAGE_TYPE.LOG_WEB3_SHIM_USAGE], implementation: logWeb3ShimUsageHandler, + hookNames: { + sendMetrics: true, + getWeb3ShimUsageState: true, + setWeb3ShimUsageRecorded: true, + }, }; export default logWeb3ShimUsage; diff --git a/app/scripts/lib/rpc-method-middleware/handlers/switch-ethereum-chain.js b/app/scripts/lib/rpc-method-middleware/handlers/switch-ethereum-chain.js index d1e3d3a22..c2d73f16b 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/switch-ethereum-chain.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/switch-ethereum-chain.js @@ -15,6 +15,13 @@ import { const switchEthereumChain = { methodNames: [MESSAGE_TYPE.SWITCH_ETHEREUM_CHAIN], implementation: switchEthereumChainHandler, + hookNames: { + getCurrentChainId: true, + findCustomRpcBy: true, + setProviderType: true, + updateRpcTarget: true, + requestUserApproval: true, + }, }; export default switchEthereumChain; diff --git a/app/scripts/lib/rpc-method-middleware/handlers/watch-asset.js b/app/scripts/lib/rpc-method-middleware/handlers/watch-asset.js index 95408eee3..a9fb503d9 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/watch-asset.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/watch-asset.js @@ -3,6 +3,9 @@ import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; const watchAsset = { methodNames: [MESSAGE_TYPE.WATCH_ASSET, MESSAGE_TYPE.WATCH_ASSET_LEGACY], implementation: watchAssetHandler, + hookNames: { + handleWatchAssetRequest: true, + }, }; export default watchAsset;