diff --git a/parity/cli/usage.txt b/parity/cli/usage.txt index 1e5f3c0fb..7ee2860b1 100644 --- a/parity/cli/usage.txt +++ b/parity/cli/usage.txt @@ -147,8 +147,9 @@ API and Console Options: (default: {flag_jsonrpc_cors:?}) --jsonrpc-apis APIS Specify the APIs available through the JSONRPC interface. APIS is a comma-delimited list of API - name. Possible name are web3, eth, net, personal, + name. Possible name are all, safe, web3, eth, net, personal, parity, parity_set, traces, rpc, parity_accounts. + You can also disable a specific API by putting '-' in the front: all,-personal (default: {flag_jsonrpc_apis}). --jsonrpc-hosts HOSTS List of allowed Host header values. This option will validate the Host header sent by the browser, it diff --git a/parity/configuration.rs b/parity/configuration.rs index f585dc22e..7061610bb 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -30,6 +30,7 @@ use ethcore::miner::{MinerOptions, Banning, StratumOptions}; use ethcore::verification::queue::VerifierSettings; use rpc::{IpcConfiguration, HttpConfiguration}; +use rpc_apis::ApiSet; use ethcore_rpc::NetworkSettings; use cache::CacheConfig; use helpers::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_price, replace_home, replace_home_for_db, @@ -718,16 +719,7 @@ impl Configuration { .collect(); if self.args.flag_geth { - apis.push("personal"); - } - - if self.args.flag_public_node { - apis.retain(|api| { - match *api { - "eth" | "net" | "parity" | "rpc" | "web3" => true, - _ => false - } - }); + apis.insert(0, "personal"); } apis.join(",") @@ -788,7 +780,10 @@ impl Configuration { enabled: self.rpc_enabled(), interface: self.rpc_interface(), port: self.args.flag_rpcport.unwrap_or(self.args.flag_jsonrpc_port), - apis: self.rpc_apis().parse()?, + apis: match self.args.flag_public_node { + false => self.rpc_apis().parse()?, + true => self.rpc_apis().parse::()?.retain(ApiSet::PublicContext), + }, hosts: self.rpc_hosts(), cors: self.rpc_cors(), threads: match self.args.flag_jsonrpc_threads { diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index ea1eabc61..cf3c0b7c9 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -85,9 +85,17 @@ impl FromStr for Api { #[derive(Debug, Clone)] pub enum ApiSet { + // Safe context (like token-protected WS interface) SafeContext, + // Unsafe context (like jsonrpc over http) UnsafeContext, + // Public context (like public jsonrpc over http) + PublicContext, + // All possible APIs + All, + // Local "unsafe" context and accounts access IpcContext, + // Fixed list of APis List(HashSet), } @@ -107,10 +115,30 @@ impl FromStr for ApiSet { type Err = String; fn from_str(s: &str) -> Result { - s.split(',') - .map(Api::from_str) - .collect::>() - .map(ApiSet::List) + let mut apis = HashSet::new(); + + for api in s.split(',') { + match api { + "all" => { + apis.extend(ApiSet::All.list_apis()); + }, + "safe" => { + // Safe APIs are those that are safe even in UnsafeContext. + apis.extend(ApiSet::UnsafeContext.list_apis()); + }, + // Remove the API + api if api.starts_with("-") => { + let api = api[1..].parse()?; + apis.remove(&api); + }, + api => { + let api = api.parse()?; + apis.insert(api); + }, + } + } + + Ok(ApiSet::List(apis)) } } @@ -403,21 +431,41 @@ impl Dependencies for LightDependencies { } impl ApiSet { + /// Retains only APIs in given set. + pub fn retain(self, set: Self) -> Self { + ApiSet::List(&self.list_apis() & &set.list_apis()) + } + pub fn list_apis(&self) -> HashSet { - let mut safe_list = vec![Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc] - .into_iter().collect(); + let mut public_list = vec![ + Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Rpc, + ].into_iter().collect(); match *self { ApiSet::List(ref apis) => apis.clone(), - ApiSet::UnsafeContext => safe_list, + ApiSet::PublicContext => public_list, + ApiSet::UnsafeContext => { + public_list.insert(Api::Traces); + public_list + }, ApiSet::IpcContext => { - safe_list.insert(Api::ParityAccounts); - safe_list + public_list.insert(Api::Traces); + public_list.insert(Api::ParityAccounts); + public_list }, ApiSet::SafeContext => { - safe_list.insert(Api::ParityAccounts); - safe_list.insert(Api::ParitySet); - safe_list.insert(Api::Signer); - safe_list + public_list.insert(Api::Traces); + public_list.insert(Api::ParityAccounts); + public_list.insert(Api::ParitySet); + public_list.insert(Api::Signer); + public_list + }, + ApiSet::All => { + public_list.insert(Api::Traces); + public_list.insert(Api::ParityAccounts); + public_list.insert(Api::ParitySet); + public_list.insert(Api::Signer); + public_list.insert(Api::Personal); + public_list }, } } @@ -493,4 +541,30 @@ mod test { ].into_iter().collect(); assert_eq!(ApiSet::SafeContext.list_apis(), expected); } + + #[test] + fn test_all_apis() { + assert_eq!("all".parse::().unwrap(), ApiSet::List(vec![ + Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, + Api::ParityAccounts, + Api::ParitySet, Api::Signer, + Api::Personal + ].into_iter().collect())); + } + + #[test] + fn test_all_without_personal_apis() { + assert_eq!("personal,all,-personal".parse::().unwrap(), ApiSet::List(vec![ + Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, + Api::ParityAccounts, + Api::ParitySet, Api::Signer, + ].into_iter().collect())); + } + + #[test] + fn test_safe_parsing() { + assert_eq!("safe".parse::().unwrap(), ApiSet::List(vec![ + Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, + ].into_iter().collect())); + } }