APIs wildcards and simple arithmetic. (#5402)

This commit is contained in:
Tomasz Drwięga 2017-04-06 19:38:33 +02:00 committed by Gav Wood
parent d74e044be4
commit f223ed21a5
3 changed files with 95 additions and 25 deletions

View File

@ -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

View File

@ -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::<ApiSet>()?.retain(ApiSet::PublicContext),
},
hosts: self.rpc_hosts(),
cors: self.rpc_cors(),
threads: match self.args.flag_jsonrpc_threads {

View File

@ -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<Api>),
}
@ -107,10 +115,30 @@ impl FromStr for ApiSet {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.split(',')
.map(Api::from_str)
.collect::<Result<_, _>>()
.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<Api> {
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::<ApiSet>().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::<ApiSet>().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::<ApiSet>().unwrap(), ApiSet::List(vec![
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc,
].into_iter().collect()));
}
}