Dapps interface RPC (#3311)
* Dapps Interface RPC * Adding JS apis * Support for signer interface in proxypac and embeds * Fixing tests * fixing tests again
This commit is contained in:
parent
eba0dd5023
commit
88c9cea04d
@ -47,7 +47,7 @@ pub struct ContentFetcher<R: URLHint = URLHintContract> {
|
|||||||
resolver: R,
|
resolver: R,
|
||||||
cache: Arc<Mutex<ContentCache>>,
|
cache: Arc<Mutex<ContentCache>>,
|
||||||
sync: Arc<SyncStatus>,
|
sync: Arc<SyncStatus>,
|
||||||
embeddable_at: Option<u16>,
|
embeddable_on: Option<(String, u16)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: URLHint> Drop for ContentFetcher<R> {
|
impl<R: URLHint> Drop for ContentFetcher<R> {
|
||||||
@ -59,7 +59,7 @@ impl<R: URLHint> Drop for ContentFetcher<R> {
|
|||||||
|
|
||||||
impl<R: URLHint> ContentFetcher<R> {
|
impl<R: URLHint> ContentFetcher<R> {
|
||||||
|
|
||||||
pub fn new(resolver: R, sync_status: Arc<SyncStatus>, embeddable_at: Option<u16>) -> Self {
|
pub fn new(resolver: R, sync_status: Arc<SyncStatus>, embeddable_on: Option<(String, u16)>) -> Self {
|
||||||
let mut dapps_path = env::temp_dir();
|
let mut dapps_path = env::temp_dir();
|
||||||
dapps_path.push(random_filename());
|
dapps_path.push(random_filename());
|
||||||
|
|
||||||
@ -68,17 +68,17 @@ impl<R: URLHint> ContentFetcher<R> {
|
|||||||
resolver: resolver,
|
resolver: resolver,
|
||||||
sync: sync_status,
|
sync: sync_status,
|
||||||
cache: Arc::new(Mutex::new(ContentCache::default())),
|
cache: Arc::new(Mutex::new(ContentCache::default())),
|
||||||
embeddable_at: embeddable_at,
|
embeddable_on: embeddable_on,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn still_syncing(port: Option<u16>) -> Box<Handler> {
|
fn still_syncing(address: Option<(String, u16)>) -> Box<Handler> {
|
||||||
Box::new(ContentHandler::error(
|
Box::new(ContentHandler::error(
|
||||||
StatusCode::ServiceUnavailable,
|
StatusCode::ServiceUnavailable,
|
||||||
"Sync In Progress",
|
"Sync In Progress",
|
||||||
"Your node is still syncing. We cannot resolve any content before it's fully synced.",
|
"Your node is still syncing. We cannot resolve any content before it's fully synced.",
|
||||||
Some("<a href=\"javascript:window.location.reload()\">Refresh</a>"),
|
Some("<a href=\"javascript:window.location.reload()\">Refresh</a>"),
|
||||||
port,
|
address,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ impl<R: URLHint> ContentFetcher<R> {
|
|||||||
match content {
|
match content {
|
||||||
// Don't serve dapps if we are still syncing (but serve content)
|
// Don't serve dapps if we are still syncing (but serve content)
|
||||||
Some(URLHintResult::Dapp(_)) if self.sync.is_major_importing() => {
|
Some(URLHintResult::Dapp(_)) if self.sync.is_major_importing() => {
|
||||||
(None, Self::still_syncing(self.embeddable_at))
|
(None, Self::still_syncing(self.embeddable_on.clone()))
|
||||||
},
|
},
|
||||||
Some(URLHintResult::Dapp(dapp)) => {
|
Some(URLHintResult::Dapp(dapp)) => {
|
||||||
let (handler, fetch_control) = ContentFetcherHandler::new(
|
let (handler, fetch_control) = ContentFetcherHandler::new(
|
||||||
@ -155,9 +155,9 @@ impl<R: URLHint> ContentFetcher<R> {
|
|||||||
id: content_id.clone(),
|
id: content_id.clone(),
|
||||||
dapps_path: self.dapps_path.clone(),
|
dapps_path: self.dapps_path.clone(),
|
||||||
on_done: Box::new(on_done),
|
on_done: Box::new(on_done),
|
||||||
embeddable_at: self.embeddable_at,
|
embeddable_on: self.embeddable_on.clone(),
|
||||||
},
|
},
|
||||||
self.embeddable_at,
|
self.embeddable_on.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
(Some(ContentStatus::Fetching(fetch_control)), Box::new(handler) as Box<Handler>)
|
(Some(ContentStatus::Fetching(fetch_control)), Box::new(handler) as Box<Handler>)
|
||||||
@ -172,13 +172,13 @@ impl<R: URLHint> ContentFetcher<R> {
|
|||||||
content_path: self.dapps_path.clone(),
|
content_path: self.dapps_path.clone(),
|
||||||
on_done: Box::new(on_done),
|
on_done: Box::new(on_done),
|
||||||
},
|
},
|
||||||
self.embeddable_at,
|
self.embeddable_on.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
(Some(ContentStatus::Fetching(fetch_control)), Box::new(handler) as Box<Handler>)
|
(Some(ContentStatus::Fetching(fetch_control)), Box::new(handler) as Box<Handler>)
|
||||||
},
|
},
|
||||||
None if self.sync.is_major_importing() => {
|
None if self.sync.is_major_importing() => {
|
||||||
(None, Self::still_syncing(self.embeddable_at))
|
(None, Self::still_syncing(self.embeddable_on.clone()))
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
// This may happen when sync status changes in between
|
// This may happen when sync status changes in between
|
||||||
@ -188,7 +188,7 @@ impl<R: URLHint> ContentFetcher<R> {
|
|||||||
"Resource Not Found",
|
"Resource Not Found",
|
||||||
"Requested resource was not found.",
|
"Requested resource was not found.",
|
||||||
None,
|
None,
|
||||||
self.embeddable_at,
|
self.embeddable_on.clone(),
|
||||||
)) as Box<Handler>)
|
)) as Box<Handler>)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -293,7 +293,7 @@ struct DappInstaller {
|
|||||||
id: String,
|
id: String,
|
||||||
dapps_path: PathBuf,
|
dapps_path: PathBuf,
|
||||||
on_done: Box<Fn(String, Option<LocalPageEndpoint>) + Send>,
|
on_done: Box<Fn(String, Option<LocalPageEndpoint>) + Send>,
|
||||||
embeddable_at: Option<u16>,
|
embeddable_on: Option<(String, u16)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DappInstaller {
|
impl DappInstaller {
|
||||||
@ -386,7 +386,7 @@ impl ContentValidator for DappInstaller {
|
|||||||
try!(manifest_file.write_all(manifest_str.as_bytes()));
|
try!(manifest_file.write_all(manifest_str.as_bytes()));
|
||||||
|
|
||||||
// Create endpoint
|
// Create endpoint
|
||||||
let app = LocalPageEndpoint::new(target, manifest.clone().into(), PageCache::Enabled, self.embeddable_at);
|
let app = LocalPageEndpoint::new(target, manifest.clone().into(), PageCache::Enabled, self.embeddable_on.clone());
|
||||||
|
|
||||||
// Return modified app manifest
|
// Return modified app manifest
|
||||||
Ok((manifest.id.clone(), app))
|
Ok((manifest.id.clone(), app))
|
||||||
|
@ -97,12 +97,12 @@ fn read_manifest(name: &str, mut path: PathBuf) -> EndpointInfo {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn local_endpoints(dapps_path: String, signer_port: Option<u16>) -> Endpoints {
|
pub fn local_endpoints(dapps_path: String, signer_address: Option<(String, u16)>) -> Endpoints {
|
||||||
let mut pages = Endpoints::new();
|
let mut pages = Endpoints::new();
|
||||||
for dapp in local_dapps(dapps_path) {
|
for dapp in local_dapps(dapps_path) {
|
||||||
pages.insert(
|
pages.insert(
|
||||||
dapp.id,
|
dapp.id,
|
||||||
Box::new(LocalPageEndpoint::new(dapp.path, dapp.info, PageCache::Disabled, signer_port))
|
Box::new(LocalPageEndpoint::new(dapp.path, dapp.info, PageCache::Disabled, signer_address.clone()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
pages
|
pages
|
||||||
|
@ -37,26 +37,26 @@ pub fn utils() -> Box<Endpoint> {
|
|||||||
Box::new(PageEndpoint::with_prefix(parity_ui::App::default(), UTILS_PATH.to_owned()))
|
Box::new(PageEndpoint::with_prefix(parity_ui::App::default(), UTILS_PATH.to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn all_endpoints(dapps_path: String, signer_port: Option<u16>) -> Endpoints {
|
pub fn all_endpoints(dapps_path: String, signer_address: Option<(String, u16)>) -> Endpoints {
|
||||||
// fetch fs dapps at first to avoid overwriting builtins
|
// fetch fs dapps at first to avoid overwriting builtins
|
||||||
let mut pages = fs::local_endpoints(dapps_path, signer_port);
|
let mut pages = fs::local_endpoints(dapps_path, signer_address.clone());
|
||||||
|
|
||||||
// NOTE [ToDr] Dapps will be currently embeded on 8180
|
// NOTE [ToDr] Dapps will be currently embeded on 8180
|
||||||
insert::<parity_ui::App>(&mut pages, "ui", Embeddable::Yes(signer_port));
|
insert::<parity_ui::App>(&mut pages, "ui", Embeddable::Yes(signer_address.clone()));
|
||||||
pages.insert("proxy".into(), ProxyPac::boxed(signer_port));
|
pages.insert("proxy".into(), ProxyPac::boxed(signer_address));
|
||||||
|
|
||||||
pages
|
pages
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert<T : WebApp + Default + 'static>(pages: &mut Endpoints, id: &str, embed_at: Embeddable) {
|
fn insert<T : WebApp + Default + 'static>(pages: &mut Endpoints, id: &str, embed_at: Embeddable) {
|
||||||
pages.insert(id.to_owned(), Box::new(match embed_at {
|
pages.insert(id.to_owned(), Box::new(match embed_at {
|
||||||
Embeddable::Yes(port) => PageEndpoint::new_safe_to_embed(T::default(), port),
|
Embeddable::Yes(address) => PageEndpoint::new_safe_to_embed(T::default(), address),
|
||||||
Embeddable::No => PageEndpoint::new(T::default()),
|
Embeddable::No => PageEndpoint::new(T::default()),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Embeddable {
|
enum Embeddable {
|
||||||
Yes(Option<u16>),
|
Yes(Option<(String, u16)>),
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
No,
|
No,
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ pub struct ContentHandler {
|
|||||||
content: String,
|
content: String,
|
||||||
mimetype: Mime,
|
mimetype: Mime,
|
||||||
write_pos: usize,
|
write_pos: usize,
|
||||||
safe_to_embed_at_port: Option<u16>,
|
safe_to_embed_on: Option<(String, u16)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ContentHandler {
|
impl ContentHandler {
|
||||||
@ -44,31 +44,31 @@ impl ContentHandler {
|
|||||||
Self::new(StatusCode::NotFound, content, mimetype)
|
Self::new(StatusCode::NotFound, content, mimetype)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn html(code: StatusCode, content: String, embeddable_at: Option<u16>) -> Self {
|
pub fn html(code: StatusCode, content: String, embeddable_on: Option<(String, u16)>) -> Self {
|
||||||
Self::new_embeddable(code, content, mime!(Text/Html), embeddable_at)
|
Self::new_embeddable(code, content, mime!(Text/Html), embeddable_on)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error(code: StatusCode, title: &str, message: &str, details: Option<&str>, embeddable_at: Option<u16>) -> Self {
|
pub fn error(code: StatusCode, title: &str, message: &str, details: Option<&str>, embeddable_on: Option<(String, u16)>) -> Self {
|
||||||
Self::html(code, format!(
|
Self::html(code, format!(
|
||||||
include_str!("../error_tpl.html"),
|
include_str!("../error_tpl.html"),
|
||||||
title=title,
|
title=title,
|
||||||
message=message,
|
message=message,
|
||||||
details=details.unwrap_or_else(|| ""),
|
details=details.unwrap_or_else(|| ""),
|
||||||
version=version(),
|
version=version(),
|
||||||
), embeddable_at)
|
), embeddable_on)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(code: StatusCode, content: String, mimetype: Mime) -> Self {
|
pub fn new(code: StatusCode, content: String, mimetype: Mime) -> Self {
|
||||||
Self::new_embeddable(code, content, mimetype, None)
|
Self::new_embeddable(code, content, mimetype, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_embeddable(code: StatusCode, content: String, mimetype: Mime, embeddable_at: Option<u16>) -> Self {
|
pub fn new_embeddable(code: StatusCode, content: String, mimetype: Mime, embeddable_on: Option<(String, u16)>) -> Self {
|
||||||
ContentHandler {
|
ContentHandler {
|
||||||
code: code,
|
code: code,
|
||||||
content: content,
|
content: content,
|
||||||
mimetype: mimetype,
|
mimetype: mimetype,
|
||||||
write_pos: 0,
|
write_pos: 0,
|
||||||
safe_to_embed_at_port: embeddable_at,
|
safe_to_embed_on: embeddable_on,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ impl server::Handler<HttpStream> for ContentHandler {
|
|||||||
fn on_response(&mut self, res: &mut server::Response) -> Next {
|
fn on_response(&mut self, res: &mut server::Response) -> Next {
|
||||||
res.set_status(self.code);
|
res.set_status(self.code);
|
||||||
res.headers_mut().set(header::ContentType(self.mimetype.clone()));
|
res.headers_mut().set(header::ContentType(self.mimetype.clone()));
|
||||||
add_security_headers(&mut res.headers_mut(), self.safe_to_embed_at_port.clone());
|
add_security_headers(&mut res.headers_mut(), self.safe_to_embed_on.clone());
|
||||||
Next::write()
|
Next::write()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ pub struct ContentFetcherHandler<H: ContentValidator> {
|
|||||||
client: Option<Client>,
|
client: Option<Client>,
|
||||||
installer: H,
|
installer: H,
|
||||||
request_url: Option<Url>,
|
request_url: Option<Url>,
|
||||||
embeddable_at: Option<u16>,
|
embeddable_on: Option<(String, u16)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H: ContentValidator> Drop for ContentFetcherHandler<H> {
|
impl<H: ContentValidator> Drop for ContentFetcherHandler<H> {
|
||||||
@ -157,7 +157,7 @@ impl<H: ContentValidator> ContentFetcherHandler<H> {
|
|||||||
url: String,
|
url: String,
|
||||||
control: Control,
|
control: Control,
|
||||||
handler: H,
|
handler: H,
|
||||||
embeddable_at: Option<u16>,
|
embeddable_on: Option<(String, u16)>,
|
||||||
) -> (Self, Arc<FetchControl>) {
|
) -> (Self, Arc<FetchControl>) {
|
||||||
|
|
||||||
let fetch_control = Arc::new(FetchControl::default());
|
let fetch_control = Arc::new(FetchControl::default());
|
||||||
@ -169,7 +169,7 @@ impl<H: ContentValidator> ContentFetcherHandler<H> {
|
|||||||
status: FetchState::NotStarted(url),
|
status: FetchState::NotStarted(url),
|
||||||
installer: handler,
|
installer: handler,
|
||||||
request_url: None,
|
request_url: None,
|
||||||
embeddable_at: embeddable_at,
|
embeddable_on: embeddable_on,
|
||||||
};
|
};
|
||||||
|
|
||||||
(handler, fetch_control)
|
(handler, fetch_control)
|
||||||
@ -208,7 +208,7 @@ impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<
|
|||||||
"Unable To Start Dapp Download",
|
"Unable To Start Dapp Download",
|
||||||
"Could not initialize download of the dapp. It might be a problem with the remote server.",
|
"Could not initialize download of the dapp. It might be a problem with the remote server.",
|
||||||
Some(&format!("{}", e)),
|
Some(&format!("{}", e)),
|
||||||
self.embeddable_at,
|
self.embeddable_on.clone(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -218,7 +218,7 @@ impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<
|
|||||||
"Method Not Allowed",
|
"Method Not Allowed",
|
||||||
"Only <code>GET</code> requests are allowed.",
|
"Only <code>GET</code> requests are allowed.",
|
||||||
None,
|
None,
|
||||||
self.embeddable_at,
|
self.embeddable_on.clone(),
|
||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
} else { None };
|
} else { None };
|
||||||
@ -241,7 +241,7 @@ impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<
|
|||||||
"Download Timeout",
|
"Download Timeout",
|
||||||
&format!("Could not fetch content within {} seconds.", FETCH_TIMEOUT),
|
&format!("Could not fetch content within {} seconds.", FETCH_TIMEOUT),
|
||||||
None,
|
None,
|
||||||
self.embeddable_at,
|
self.embeddable_on.clone(),
|
||||||
);
|
);
|
||||||
Self::close_client(&mut self.client);
|
Self::close_client(&mut self.client);
|
||||||
(Some(FetchState::Error(timeout)), Next::write())
|
(Some(FetchState::Error(timeout)), Next::write())
|
||||||
@ -263,7 +263,7 @@ impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<
|
|||||||
"Invalid Dapp",
|
"Invalid Dapp",
|
||||||
"Downloaded bundle does not contain a valid content.",
|
"Downloaded bundle does not contain a valid content.",
|
||||||
Some(&format!("{:?}", e)),
|
Some(&format!("{:?}", e)),
|
||||||
self.embeddable_at,
|
self.embeddable_on.clone(),
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
Ok((id, result)) => {
|
Ok((id, result)) => {
|
||||||
@ -284,7 +284,7 @@ impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<
|
|||||||
"Download Error",
|
"Download Error",
|
||||||
"There was an error when fetching the content.",
|
"There was an error when fetching the content.",
|
||||||
Some(&format!("{:?}", e)),
|
Some(&format!("{:?}", e)),
|
||||||
self.embeddable_at,
|
self.embeddable_on.clone(),
|
||||||
);
|
);
|
||||||
(Some(FetchState::Error(error)), Next::write())
|
(Some(FetchState::Error(error)), Next::write())
|
||||||
},
|
},
|
||||||
|
@ -30,18 +30,18 @@ pub use self::fetch::{ContentFetcherHandler, ContentValidator, FetchControl};
|
|||||||
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use hyper::{server, header, net, uri};
|
use hyper::{server, header, net, uri};
|
||||||
use signer_address;
|
use address;
|
||||||
|
|
||||||
/// Adds security-related headers to the Response.
|
/// Adds security-related headers to the Response.
|
||||||
pub fn add_security_headers(headers: &mut header::Headers, embeddable_at: Option<u16>) {
|
pub fn add_security_headers(headers: &mut header::Headers, embeddable_on: Option<(String, u16)>) {
|
||||||
headers.set_raw("X-XSS-Protection", vec![b"1; mode=block".to_vec()]);
|
headers.set_raw("X-XSS-Protection", vec![b"1; mode=block".to_vec()]);
|
||||||
headers.set_raw("X-Content-Type-Options", vec![b"nosniff".to_vec()]);
|
headers.set_raw("X-Content-Type-Options", vec![b"nosniff".to_vec()]);
|
||||||
|
|
||||||
// Embedding header:
|
// Embedding header:
|
||||||
if let Some(port) = embeddable_at {
|
if let Some(embeddable_on) = embeddable_on {
|
||||||
headers.set_raw(
|
headers.set_raw(
|
||||||
"X-Frame-Options",
|
"X-Frame-Options",
|
||||||
vec![format!("ALLOW-FROM http://{}", signer_address(port)).into_bytes()]
|
vec![format!("ALLOW-FROM http://{}", address(embeddable_on)).into_bytes()]
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// TODO [ToDr] Should we be more strict here (DENY?)?
|
// TODO [ToDr] Should we be more strict here (DENY?)?
|
||||||
|
@ -112,7 +112,7 @@ pub struct ServerBuilder {
|
|||||||
handler: Arc<IoHandler>,
|
handler: Arc<IoHandler>,
|
||||||
registrar: Arc<ContractClient>,
|
registrar: Arc<ContractClient>,
|
||||||
sync_status: Arc<SyncStatus>,
|
sync_status: Arc<SyncStatus>,
|
||||||
signer_port: Option<u16>,
|
signer_address: Option<(String, u16)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Extendable for ServerBuilder {
|
impl Extendable for ServerBuilder {
|
||||||
@ -129,7 +129,7 @@ impl ServerBuilder {
|
|||||||
handler: Arc::new(IoHandler::new()),
|
handler: Arc::new(IoHandler::new()),
|
||||||
registrar: registrar,
|
registrar: registrar,
|
||||||
sync_status: Arc::new(|| false),
|
sync_status: Arc::new(|| false),
|
||||||
signer_port: None,
|
signer_address: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,8 +139,8 @@ impl ServerBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Change default signer port.
|
/// Change default signer port.
|
||||||
pub fn with_signer_port(&mut self, signer_port: Option<u16>) {
|
pub fn with_signer_address(&mut self, signer_address: Option<(String, u16)>) {
|
||||||
self.signer_port = signer_port;
|
self.signer_address = signer_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Asynchronously start server with no authentication,
|
/// Asynchronously start server with no authentication,
|
||||||
@ -152,7 +152,7 @@ impl ServerBuilder {
|
|||||||
NoAuth,
|
NoAuth,
|
||||||
self.handler.clone(),
|
self.handler.clone(),
|
||||||
self.dapps_path.clone(),
|
self.dapps_path.clone(),
|
||||||
self.signer_port.clone(),
|
self.signer_address.clone(),
|
||||||
self.registrar.clone(),
|
self.registrar.clone(),
|
||||||
self.sync_status.clone(),
|
self.sync_status.clone(),
|
||||||
)
|
)
|
||||||
@ -167,7 +167,7 @@ impl ServerBuilder {
|
|||||||
HttpBasicAuth::single_user(username, password),
|
HttpBasicAuth::single_user(username, password),
|
||||||
self.handler.clone(),
|
self.handler.clone(),
|
||||||
self.dapps_path.clone(),
|
self.dapps_path.clone(),
|
||||||
self.signer_port.clone(),
|
self.signer_address.clone(),
|
||||||
self.registrar.clone(),
|
self.registrar.clone(),
|
||||||
self.sync_status.clone(),
|
self.sync_status.clone(),
|
||||||
)
|
)
|
||||||
@ -197,11 +197,11 @@ impl Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a list of CORS domains for API endpoint.
|
/// Returns a list of CORS domains for API endpoint.
|
||||||
fn cors_domains(signer_port: Option<u16>) -> Vec<String> {
|
fn cors_domains(signer_address: Option<(String, u16)>) -> Vec<String> {
|
||||||
match signer_port {
|
match signer_address {
|
||||||
Some(port) => vec![
|
Some(signer_address) => vec![
|
||||||
format!("http://{}{}", HOME_PAGE, DAPPS_DOMAIN),
|
format!("http://{}{}", HOME_PAGE, DAPPS_DOMAIN),
|
||||||
format!("http://{}", signer_address(port)),
|
format!("http://{}", address(signer_address)),
|
||||||
],
|
],
|
||||||
None => vec![],
|
None => vec![],
|
||||||
}
|
}
|
||||||
@ -213,15 +213,15 @@ impl Server {
|
|||||||
authorization: A,
|
authorization: A,
|
||||||
handler: Arc<IoHandler>,
|
handler: Arc<IoHandler>,
|
||||||
dapps_path: String,
|
dapps_path: String,
|
||||||
signer_port: Option<u16>,
|
signer_address: Option<(String, u16)>,
|
||||||
registrar: Arc<ContractClient>,
|
registrar: Arc<ContractClient>,
|
||||||
sync_status: Arc<SyncStatus>,
|
sync_status: Arc<SyncStatus>,
|
||||||
) -> Result<Server, ServerError> {
|
) -> Result<Server, ServerError> {
|
||||||
let panic_handler = Arc::new(Mutex::new(None));
|
let panic_handler = Arc::new(Mutex::new(None));
|
||||||
let authorization = Arc::new(authorization);
|
let authorization = Arc::new(authorization);
|
||||||
let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(apps::urlhint::URLHintContract::new(registrar), sync_status, signer_port));
|
let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(apps::urlhint::URLHintContract::new(registrar), sync_status, signer_address.clone()));
|
||||||
let endpoints = Arc::new(apps::all_endpoints(dapps_path, signer_port.clone()));
|
let endpoints = Arc::new(apps::all_endpoints(dapps_path, signer_address.clone()));
|
||||||
let cors_domains = Self::cors_domains(signer_port);
|
let cors_domains = Self::cors_domains(signer_address.clone());
|
||||||
|
|
||||||
let special = Arc::new({
|
let special = Arc::new({
|
||||||
let mut special = HashMap::new();
|
let mut special = HashMap::new();
|
||||||
@ -238,7 +238,7 @@ impl Server {
|
|||||||
try!(hyper::Server::http(addr))
|
try!(hyper::Server::http(addr))
|
||||||
.handle(move |ctrl| router::Router::new(
|
.handle(move |ctrl| router::Router::new(
|
||||||
ctrl,
|
ctrl,
|
||||||
signer_port.clone(),
|
signer_address.clone(),
|
||||||
content_fetcher.clone(),
|
content_fetcher.clone(),
|
||||||
endpoints.clone(),
|
endpoints.clone(),
|
||||||
special.clone(),
|
special.clone(),
|
||||||
@ -302,8 +302,8 @@ pub fn random_filename() -> String {
|
|||||||
rng.gen_ascii_chars().take(12).collect()
|
rng.gen_ascii_chars().take(12).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signer_address(port: u16) -> String {
|
fn address(address: (String, u16)) -> String {
|
||||||
format!("127.0.0.1:{}", port)
|
format!("{}:{}", address.0, address.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -332,7 +332,7 @@ mod util_tests {
|
|||||||
|
|
||||||
// when
|
// when
|
||||||
let none = Server::cors_domains(None);
|
let none = Server::cors_domains(None);
|
||||||
let some = Server::cors_domains(Some(18180));
|
let some = Server::cors_domains(Some(("127.0.0.1".into(), 18180)));
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(none, Vec::<String>::new());
|
assert_eq!(none, Vec::<String>::new());
|
||||||
|
@ -25,7 +25,7 @@ pub struct PageEndpoint<T : WebApp + 'static> {
|
|||||||
/// Prefix to strip from the path (when `None` deducted from `app_id`)
|
/// Prefix to strip from the path (when `None` deducted from `app_id`)
|
||||||
pub prefix: Option<String>,
|
pub prefix: Option<String>,
|
||||||
/// Safe to be loaded in frame by other origin. (use wisely!)
|
/// Safe to be loaded in frame by other origin. (use wisely!)
|
||||||
safe_to_embed_at_port: Option<u16>,
|
safe_to_embed_on: Option<(String, u16)>,
|
||||||
info: EndpointInfo,
|
info: EndpointInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ impl<T: WebApp + 'static> PageEndpoint<T> {
|
|||||||
PageEndpoint {
|
PageEndpoint {
|
||||||
app: Arc::new(app),
|
app: Arc::new(app),
|
||||||
prefix: None,
|
prefix: None,
|
||||||
safe_to_embed_at_port: None,
|
safe_to_embed_on: None,
|
||||||
info: EndpointInfo::from(info),
|
info: EndpointInfo::from(info),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,7 +49,7 @@ impl<T: WebApp + 'static> PageEndpoint<T> {
|
|||||||
PageEndpoint {
|
PageEndpoint {
|
||||||
app: Arc::new(app),
|
app: Arc::new(app),
|
||||||
prefix: Some(prefix),
|
prefix: Some(prefix),
|
||||||
safe_to_embed_at_port: None,
|
safe_to_embed_on: None,
|
||||||
info: EndpointInfo::from(info),
|
info: EndpointInfo::from(info),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,12 +57,12 @@ impl<T: WebApp + 'static> PageEndpoint<T> {
|
|||||||
/// Creates new `PageEndpoint` which can be safely used in iframe
|
/// Creates new `PageEndpoint` which can be safely used in iframe
|
||||||
/// even from different origin. It might be dangerous (clickjacking).
|
/// even from different origin. It might be dangerous (clickjacking).
|
||||||
/// Use wisely!
|
/// Use wisely!
|
||||||
pub fn new_safe_to_embed(app: T, port: Option<u16>) -> Self {
|
pub fn new_safe_to_embed(app: T, address: Option<(String, u16)>) -> Self {
|
||||||
let info = app.info();
|
let info = app.info();
|
||||||
PageEndpoint {
|
PageEndpoint {
|
||||||
app: Arc::new(app),
|
app: Arc::new(app),
|
||||||
prefix: None,
|
prefix: None,
|
||||||
safe_to_embed_at_port: port,
|
safe_to_embed_on: address,
|
||||||
info: EndpointInfo::from(info),
|
info: EndpointInfo::from(info),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,9 +79,9 @@ impl<T: WebApp> Endpoint for PageEndpoint<T> {
|
|||||||
app: BuiltinDapp::new(self.app.clone()),
|
app: BuiltinDapp::new(self.app.clone()),
|
||||||
prefix: self.prefix.clone(),
|
prefix: self.prefix.clone(),
|
||||||
path: path,
|
path: path,
|
||||||
file: handler::ServedFile::new(self.safe_to_embed_at_port.clone()),
|
file: handler::ServedFile::new(self.safe_to_embed_on.clone()),
|
||||||
cache: PageCache::Disabled,
|
cache: PageCache::Disabled,
|
||||||
safe_to_embed_at_port: self.safe_to_embed_at_port.clone(),
|
safe_to_embed_on: self.safe_to_embed_on.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,13 +60,13 @@ pub enum ServedFile<T: Dapp> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Dapp> ServedFile<T> {
|
impl<T: Dapp> ServedFile<T> {
|
||||||
pub fn new(embeddable_at: Option<u16>) -> Self {
|
pub fn new(embeddable_on: Option<(String, u16)>) -> Self {
|
||||||
ServedFile::Error(ContentHandler::error(
|
ServedFile::Error(ContentHandler::error(
|
||||||
StatusCode::NotFound,
|
StatusCode::NotFound,
|
||||||
"404 Not Found",
|
"404 Not Found",
|
||||||
"Requested dapp resource was not found.",
|
"Requested dapp resource was not found.",
|
||||||
None,
|
None,
|
||||||
embeddable_at,
|
embeddable_on,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@ pub struct PageHandler<T: Dapp> {
|
|||||||
/// Requested path.
|
/// Requested path.
|
||||||
pub path: EndpointPath,
|
pub path: EndpointPath,
|
||||||
/// Flag indicating if the file can be safely embeded (put in iframe).
|
/// Flag indicating if the file can be safely embeded (put in iframe).
|
||||||
pub safe_to_embed_at_port: Option<u16>,
|
pub safe_to_embed_on: Option<(String, u16)>,
|
||||||
/// Cache settings for this page.
|
/// Cache settings for this page.
|
||||||
pub cache: PageCache,
|
pub cache: PageCache,
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ impl<T: Dapp> server::Handler<HttpStream> for PageHandler<T> {
|
|||||||
self.app.file(&self.extract_path(url.path()))
|
self.app.file(&self.extract_path(url.path()))
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}.map_or_else(|| ServedFile::new(self.safe_to_embed_at_port.clone()), |f| ServedFile::File(f));
|
}.map_or_else(|| ServedFile::new(self.safe_to_embed_on.clone()), |f| ServedFile::File(f));
|
||||||
Next::write()
|
Next::write()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +162,7 @@ impl<T: Dapp> server::Handler<HttpStream> for PageHandler<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Security headers:
|
// Security headers:
|
||||||
add_security_headers(&mut res.headers_mut(), self.safe_to_embed_at_port);
|
add_security_headers(&mut res.headers_mut(), self.safe_to_embed_on.clone());
|
||||||
Next::write()
|
Next::write()
|
||||||
},
|
},
|
||||||
ServedFile::Error(ref mut handler) => {
|
ServedFile::Error(ref mut handler) => {
|
||||||
@ -246,7 +246,7 @@ fn should_extract_path_with_appid() {
|
|||||||
},
|
},
|
||||||
file: ServedFile::new(None),
|
file: ServedFile::new(None),
|
||||||
cache: Default::default(),
|
cache: Default::default(),
|
||||||
safe_to_embed_at_port: None,
|
safe_to_embed_on: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// when
|
// when
|
||||||
|
@ -27,17 +27,17 @@ pub struct LocalPageEndpoint {
|
|||||||
mime: Option<String>,
|
mime: Option<String>,
|
||||||
info: Option<EndpointInfo>,
|
info: Option<EndpointInfo>,
|
||||||
cache: PageCache,
|
cache: PageCache,
|
||||||
embeddable_at: Option<u16>,
|
embeddable_on: Option<(String, u16)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalPageEndpoint {
|
impl LocalPageEndpoint {
|
||||||
pub fn new(path: PathBuf, info: EndpointInfo, cache: PageCache, embeddable_at: Option<u16>) -> Self {
|
pub fn new(path: PathBuf, info: EndpointInfo, cache: PageCache, embeddable_on: Option<(String, u16)>) -> Self {
|
||||||
LocalPageEndpoint {
|
LocalPageEndpoint {
|
||||||
path: path,
|
path: path,
|
||||||
mime: None,
|
mime: None,
|
||||||
info: Some(info),
|
info: Some(info),
|
||||||
cache: cache,
|
cache: cache,
|
||||||
embeddable_at: embeddable_at,
|
embeddable_on: embeddable_on,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ impl LocalPageEndpoint {
|
|||||||
mime: Some(mime),
|
mime: Some(mime),
|
||||||
info: None,
|
info: None,
|
||||||
cache: cache,
|
cache: cache,
|
||||||
embeddable_at: None,
|
embeddable_on: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ impl Endpoint for LocalPageEndpoint {
|
|||||||
prefix: None,
|
prefix: None,
|
||||||
path: path,
|
path: path,
|
||||||
file: handler::ServedFile::new(None),
|
file: handler::ServedFile::new(None),
|
||||||
safe_to_embed_at_port: self.embeddable_at,
|
safe_to_embed_on: self.embeddable_on.clone(),
|
||||||
cache: self.cache,
|
cache: self.cache,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -77,7 +77,7 @@ impl Endpoint for LocalPageEndpoint {
|
|||||||
prefix: None,
|
prefix: None,
|
||||||
path: path,
|
path: path,
|
||||||
file: handler::ServedFile::new(None),
|
file: handler::ServedFile::new(None),
|
||||||
safe_to_embed_at_port: self.embeddable_at,
|
safe_to_embed_on: self.embeddable_on.clone(),
|
||||||
cache: self.cache,
|
cache: self.cache,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -19,24 +19,24 @@
|
|||||||
use endpoint::{Endpoint, Handler, EndpointPath};
|
use endpoint::{Endpoint, Handler, EndpointPath};
|
||||||
use handlers::ContentHandler;
|
use handlers::ContentHandler;
|
||||||
use apps::{HOME_PAGE, DAPPS_DOMAIN};
|
use apps::{HOME_PAGE, DAPPS_DOMAIN};
|
||||||
use signer_address;
|
use address;
|
||||||
|
|
||||||
pub struct ProxyPac {
|
pub struct ProxyPac {
|
||||||
signer_port: Option<u16>,
|
signer_address: Option<(String, u16)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProxyPac {
|
impl ProxyPac {
|
||||||
pub fn boxed(signer_port: Option<u16>) -> Box<Endpoint> {
|
pub fn boxed(signer_address: Option<(String, u16)>) -> Box<Endpoint> {
|
||||||
Box::new(ProxyPac {
|
Box::new(ProxyPac {
|
||||||
signer_port: signer_port
|
signer_address: signer_address
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Endpoint for ProxyPac {
|
impl Endpoint for ProxyPac {
|
||||||
fn to_handler(&self, path: EndpointPath) -> Box<Handler> {
|
fn to_handler(&self, path: EndpointPath) -> Box<Handler> {
|
||||||
let signer = self.signer_port
|
let signer = self.signer_address.clone()
|
||||||
.map(signer_address)
|
.map(address)
|
||||||
.unwrap_or_else(|| format!("{}:{}", path.host, path.port));
|
.unwrap_or_else(|| format!("{}:{}", path.host, path.port));
|
||||||
|
|
||||||
let content = format!(
|
let content = format!(
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
pub mod auth;
|
pub mod auth;
|
||||||
mod host_validation;
|
mod host_validation;
|
||||||
|
|
||||||
use signer_address;
|
use address;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use url::{Url, Host};
|
use url::{Url, Host};
|
||||||
@ -43,7 +43,7 @@ pub enum SpecialEndpoint {
|
|||||||
|
|
||||||
pub struct Router<A: Authorization + 'static> {
|
pub struct Router<A: Authorization + 'static> {
|
||||||
control: Option<Control>,
|
control: Option<Control>,
|
||||||
signer_port: Option<u16>,
|
signer_address: Option<(String, u16)>,
|
||||||
endpoints: Arc<Endpoints>,
|
endpoints: Arc<Endpoints>,
|
||||||
fetch: Arc<ContentFetcher>,
|
fetch: Arc<ContentFetcher>,
|
||||||
special: Arc<HashMap<SpecialEndpoint, Box<Endpoint>>>,
|
special: Arc<HashMap<SpecialEndpoint, Box<Endpoint>>>,
|
||||||
@ -117,14 +117,14 @@ impl<A: Authorization + 'static> server::Handler<HttpStream> for Router<A> {
|
|||||||
"404 Not Found",
|
"404 Not Found",
|
||||||
"Requested content was not found.",
|
"Requested content was not found.",
|
||||||
None,
|
None,
|
||||||
self.signer_port,
|
self.signer_address.clone(),
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
// Redirect any other GET request to signer.
|
// Redirect any other GET request to signer.
|
||||||
_ if *req.method() == hyper::Method::Get => {
|
_ if *req.method() == hyper::Method::Get => {
|
||||||
if let Some(port) = self.signer_port {
|
if let Some(signer_address) = self.signer_address.clone() {
|
||||||
trace!(target: "dapps", "Redirecting to signer interface.");
|
trace!(target: "dapps", "Redirecting to signer interface.");
|
||||||
Redirection::boxed(&format!("http://{}", signer_address(port)))
|
Redirection::boxed(&format!("http://{}", address(signer_address)))
|
||||||
} else {
|
} else {
|
||||||
trace!(target: "dapps", "Signer disabled, returning 404.");
|
trace!(target: "dapps", "Signer disabled, returning 404.");
|
||||||
Box::new(ContentHandler::error(
|
Box::new(ContentHandler::error(
|
||||||
@ -132,7 +132,7 @@ impl<A: Authorization + 'static> server::Handler<HttpStream> for Router<A> {
|
|||||||
"404 Not Found",
|
"404 Not Found",
|
||||||
"Your homepage is not available when Trusted Signer is disabled.",
|
"Your homepage is not available when Trusted Signer is disabled.",
|
||||||
Some("You can still access dapps by writing a correct address, though. Re-enabled Signer to get your homepage back."),
|
Some("You can still access dapps by writing a correct address, though. Re-enabled Signer to get your homepage back."),
|
||||||
self.signer_port,
|
self.signer_address.clone(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -168,7 +168,7 @@ impl<A: Authorization + 'static> server::Handler<HttpStream> for Router<A> {
|
|||||||
impl<A: Authorization> Router<A> {
|
impl<A: Authorization> Router<A> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
control: Control,
|
control: Control,
|
||||||
signer_port: Option<u16>,
|
signer_address: Option<(String, u16)>,
|
||||||
content_fetcher: Arc<ContentFetcher>,
|
content_fetcher: Arc<ContentFetcher>,
|
||||||
endpoints: Arc<Endpoints>,
|
endpoints: Arc<Endpoints>,
|
||||||
special: Arc<HashMap<SpecialEndpoint, Box<Endpoint>>>,
|
special: Arc<HashMap<SpecialEndpoint, Box<Endpoint>>>,
|
||||||
@ -181,7 +181,7 @@ impl<A: Authorization> Router<A> {
|
|||||||
.to_handler(EndpointPath::default());
|
.to_handler(EndpointPath::default());
|
||||||
Router {
|
Router {
|
||||||
control: Some(control),
|
control: Some(control),
|
||||||
signer_port: signer_port,
|
signer_address: signer_address,
|
||||||
endpoints: endpoints,
|
endpoints: endpoints,
|
||||||
fetch: content_fetcher,
|
fetch: content_fetcher,
|
||||||
special: special,
|
special: special,
|
||||||
|
@ -76,7 +76,7 @@ pub fn init_server(hosts: Option<Vec<String>>, is_syncing: bool) -> (Server, Arc
|
|||||||
dapps_path.push("non-existent-dir-to-prevent-fs-files-from-loading");
|
dapps_path.push("non-existent-dir-to-prevent-fs-files-from-loading");
|
||||||
let mut builder = ServerBuilder::new(dapps_path.to_str().unwrap().into(), registrar.clone());
|
let mut builder = ServerBuilder::new(dapps_path.to_str().unwrap().into(), registrar.clone());
|
||||||
builder.with_sync_status(Arc::new(move || is_syncing));
|
builder.with_sync_status(Arc::new(move || is_syncing));
|
||||||
builder.with_signer_port(Some(SIGNER_PORT));
|
builder.with_signer_address(Some(("127.0.0.1".into(), SIGNER_PORT)));
|
||||||
(
|
(
|
||||||
builder.start_unsecured_http(&"127.0.0.1:0".parse().unwrap(), hosts).unwrap(),
|
builder.start_unsecured_http(&"127.0.0.1:0".parse().unwrap(), hosts).unwrap(),
|
||||||
registrar,
|
registrar,
|
||||||
@ -89,7 +89,7 @@ pub fn serve_with_auth(user: &str, pass: &str) -> Server {
|
|||||||
let mut dapps_path = env::temp_dir();
|
let mut dapps_path = env::temp_dir();
|
||||||
dapps_path.push("non-existent-dir-to-prevent-fs-files-from-loading");
|
dapps_path.push("non-existent-dir-to-prevent-fs-files-from-loading");
|
||||||
let mut builder = ServerBuilder::new(dapps_path.to_str().unwrap().into(), registrar);
|
let mut builder = ServerBuilder::new(dapps_path.to_str().unwrap().into(), registrar);
|
||||||
builder.with_signer_port(Some(SIGNER_PORT));
|
builder.with_signer_address(Some(("127.0.0.1".into(), SIGNER_PORT)));
|
||||||
builder.start_basic_auth_http(&"127.0.0.1:0".parse().unwrap(), None, user, pass).unwrap()
|
builder.start_basic_auth_http(&"127.0.0.1:0".parse().unwrap(), None, user, pass).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +60,11 @@ export default class Parity {
|
|||||||
.then(outNumber);
|
.then(outNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dappsInterface () {
|
||||||
|
return this._transport
|
||||||
|
.execute('parity_dappsInterface');
|
||||||
|
}
|
||||||
|
|
||||||
defaultExtraData () {
|
defaultExtraData () {
|
||||||
return this._transport
|
return this._transport
|
||||||
.execute('parity_defaultExtraData');
|
.execute('parity_defaultExtraData');
|
||||||
|
@ -109,6 +109,15 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
dappsInterface: {
|
||||||
|
desc: 'Returns the interface the dapps are running on, error if not enabled',
|
||||||
|
params: [],
|
||||||
|
returns: {
|
||||||
|
type: String,
|
||||||
|
desc: 'The interface'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
defaultExtraData: {
|
defaultExtraData: {
|
||||||
desc: 'Returns the default extra data',
|
desc: 'Returns the default extra data',
|
||||||
params: [],
|
params: [],
|
||||||
|
@ -95,7 +95,7 @@ impl Configuration {
|
|||||||
let wal = !self.args.flag_fast_and_loose;
|
let wal = !self.args.flag_fast_and_loose;
|
||||||
let warp_sync = self.args.flag_warp;
|
let warp_sync = self.args.flag_warp;
|
||||||
let geth_compatibility = self.args.flag_geth;
|
let geth_compatibility = self.args.flag_geth;
|
||||||
let ui_port = self.ui_port();
|
let ui_address = self.ui_port().map(|port| (self.ui_interface(), port));
|
||||||
let dapps_conf = self.dapps_config();
|
let dapps_conf = self.dapps_config();
|
||||||
let signer_conf = self.signer_config();
|
let signer_conf = self.signer_config();
|
||||||
let format = try!(self.format());
|
let format = try!(self.format());
|
||||||
@ -243,7 +243,7 @@ impl Configuration {
|
|||||||
vm_type: vm_type,
|
vm_type: vm_type,
|
||||||
warp_sync: warp_sync,
|
warp_sync: warp_sync,
|
||||||
geth_compatibility: geth_compatibility,
|
geth_compatibility: geth_compatibility,
|
||||||
ui_port: ui_port,
|
ui_address: ui_address,
|
||||||
net_settings: self.network_settings(),
|
net_settings: self.network_settings(),
|
||||||
dapps_conf: dapps_conf,
|
dapps_conf: dapps_conf,
|
||||||
signer_conf: signer_conf,
|
signer_conf: signer_conf,
|
||||||
@ -859,7 +859,7 @@ mod tests {
|
|||||||
wal: true,
|
wal: true,
|
||||||
vm_type: Default::default(),
|
vm_type: Default::default(),
|
||||||
geth_compatibility: false,
|
geth_compatibility: false,
|
||||||
ui_port: Some(8180),
|
ui_address: Some(("127.0.0.1".into(), 8180)),
|
||||||
net_settings: Default::default(),
|
net_settings: Default::default(),
|
||||||
dapps_conf: Default::default(),
|
dapps_conf: Default::default(),
|
||||||
signer_conf: Default::default(),
|
signer_conf: Default::default(),
|
||||||
|
@ -58,7 +58,7 @@ pub fn new(configuration: Configuration, deps: Dependencies) -> Result<Option<We
|
|||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let signer_port = deps.apis.signer_service.port();
|
let signer_address = deps.apis.signer_service.address();
|
||||||
let url = format!("{}:{}", configuration.interface, configuration.port);
|
let url = format!("{}:{}", configuration.interface, configuration.port);
|
||||||
let addr = try!(url.parse().map_err(|_| format!("Invalid Webapps listen host/port given: {}", url)));
|
let addr = try!(url.parse().map_err(|_| format!("Invalid Webapps listen host/port given: {}", url)));
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ pub fn new(configuration: Configuration, deps: Dependencies) -> Result<Option<We
|
|||||||
(username.to_owned(), password)
|
(username.to_owned(), password)
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(Some(try!(setup_dapps_server(deps, configuration.dapps_path, &addr, configuration.hosts, auth, signer_port))))
|
Ok(Some(try!(setup_dapps_server(deps, configuration.dapps_path, &addr, configuration.hosts, auth, signer_address))))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use self::server::WebappServer;
|
pub use self::server::WebappServer;
|
||||||
@ -91,7 +91,7 @@ mod server {
|
|||||||
_url: &SocketAddr,
|
_url: &SocketAddr,
|
||||||
_allowed_hosts: Option<Vec<String>>,
|
_allowed_hosts: Option<Vec<String>>,
|
||||||
_auth: Option<(String, String)>,
|
_auth: Option<(String, String)>,
|
||||||
_signer_port: Option<u16>,
|
_signer_address: Option<(String, u16)>,
|
||||||
) -> Result<WebappServer, String> {
|
) -> Result<WebappServer, String> {
|
||||||
Err("Your Parity version has been compiled without WebApps support.".into())
|
Err("Your Parity version has been compiled without WebApps support.".into())
|
||||||
}
|
}
|
||||||
@ -120,7 +120,7 @@ mod server {
|
|||||||
url: &SocketAddr,
|
url: &SocketAddr,
|
||||||
allowed_hosts: Option<Vec<String>>,
|
allowed_hosts: Option<Vec<String>>,
|
||||||
auth: Option<(String, String)>,
|
auth: Option<(String, String)>,
|
||||||
signer_port: Option<u16>,
|
signer_address: Option<(String, u16)>,
|
||||||
) -> Result<WebappServer, String> {
|
) -> Result<WebappServer, String> {
|
||||||
use ethcore_dapps as dapps;
|
use ethcore_dapps as dapps;
|
||||||
|
|
||||||
@ -131,7 +131,7 @@ mod server {
|
|||||||
let sync = deps.sync.clone();
|
let sync = deps.sync.clone();
|
||||||
let client = deps.client.clone();
|
let client = deps.client.clone();
|
||||||
server.with_sync_status(Arc::new(move || is_major_importing(Some(sync.status().state), client.queue_info())));
|
server.with_sync_status(Arc::new(move || is_major_importing(Some(sync.status().state), client.queue_info())));
|
||||||
server.with_signer_port(signer_port);
|
server.with_signer_address(signer_address);
|
||||||
|
|
||||||
let server = rpc_apis::setup_rpc(server, deps.apis.clone(), rpc_apis::ApiSet::UnsafeContext);
|
let server = rpc_apis::setup_rpc(server, deps.apis.clone(), rpc_apis::ApiSet::UnsafeContext);
|
||||||
let start_result = match auth {
|
let start_result = match auth {
|
||||||
|
@ -119,6 +119,7 @@ pub struct Dependencies {
|
|||||||
pub settings: Arc<NetworkSettings>,
|
pub settings: Arc<NetworkSettings>,
|
||||||
pub net_service: Arc<ManageNetwork>,
|
pub net_service: Arc<ManageNetwork>,
|
||||||
pub geth_compatibility: bool,
|
pub geth_compatibility: bool,
|
||||||
|
pub dapps_interface: Option<String>,
|
||||||
pub dapps_port: Option<u16>,
|
pub dapps_port: Option<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,6 +229,7 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
|
|||||||
deps.logger.clone(),
|
deps.logger.clone(),
|
||||||
deps.settings.clone(),
|
deps.settings.clone(),
|
||||||
signer,
|
signer,
|
||||||
|
deps.dapps_interface.clone(),
|
||||||
deps.dapps_port,
|
deps.dapps_port,
|
||||||
).to_delegate());
|
).to_delegate());
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ pub struct RunCmd {
|
|||||||
pub wal: bool,
|
pub wal: bool,
|
||||||
pub vm_type: VMType,
|
pub vm_type: VMType,
|
||||||
pub geth_compatibility: bool,
|
pub geth_compatibility: bool,
|
||||||
pub ui_port: Option<u16>,
|
pub ui_address: Option<(String, u16)>,
|
||||||
pub net_settings: NetworkSettings,
|
pub net_settings: NetworkSettings,
|
||||||
pub dapps_conf: dapps::Configuration,
|
pub dapps_conf: dapps::Configuration,
|
||||||
pub signer_conf: signer::Configuration,
|
pub signer_conf: signer::Configuration,
|
||||||
@ -262,7 +262,7 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
|||||||
let deps_for_rpc_apis = Arc::new(rpc_apis::Dependencies {
|
let deps_for_rpc_apis = Arc::new(rpc_apis::Dependencies {
|
||||||
signer_service: Arc::new(rpc_apis::SignerService::new(move || {
|
signer_service: Arc::new(rpc_apis::SignerService::new(move || {
|
||||||
signer::generate_new_token(signer_path.clone()).map_err(|e| format!("{:?}", e))
|
signer::generate_new_token(signer_path.clone()).map_err(|e| format!("{:?}", e))
|
||||||
}, cmd.ui_port)),
|
}, cmd.ui_address)),
|
||||||
snapshot: snapshot_service.clone(),
|
snapshot: snapshot_service.clone(),
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
sync: sync_provider.clone(),
|
sync: sync_provider.clone(),
|
||||||
@ -274,6 +274,10 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
|||||||
settings: Arc::new(cmd.net_settings.clone()),
|
settings: Arc::new(cmd.net_settings.clone()),
|
||||||
net_service: manage_network.clone(),
|
net_service: manage_network.clone(),
|
||||||
geth_compatibility: cmd.geth_compatibility,
|
geth_compatibility: cmd.geth_compatibility,
|
||||||
|
dapps_interface: match cmd.dapps_conf.enabled {
|
||||||
|
true => Some(cmd.dapps_conf.interface.clone()),
|
||||||
|
false => None,
|
||||||
|
},
|
||||||
dapps_port: match cmd.dapps_conf.enabled {
|
dapps_port: match cmd.dapps_conf.enabled {
|
||||||
true => Some(cmd.dapps_conf.port),
|
true => Some(cmd.dapps_conf.port),
|
||||||
false => None,
|
false => None,
|
||||||
|
@ -22,18 +22,18 @@ use v1::helpers::signing_queue::{ConfirmationsQueue};
|
|||||||
pub struct SignerService {
|
pub struct SignerService {
|
||||||
queue: Arc<ConfirmationsQueue>,
|
queue: Arc<ConfirmationsQueue>,
|
||||||
generate_new_token: Box<Fn() -> Result<String, String> + Send + Sync + 'static>,
|
generate_new_token: Box<Fn() -> Result<String, String> + Send + Sync + 'static>,
|
||||||
port: Option<u16>,
|
address: Option<(String, u16)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SignerService {
|
impl SignerService {
|
||||||
|
|
||||||
/// Creates new Signer Service given function to generate new tokens.
|
/// Creates new Signer Service given function to generate new tokens.
|
||||||
pub fn new<F>(new_token: F, port: Option<u16>) -> Self
|
pub fn new<F>(new_token: F, address: Option<(String, u16)>) -> Self
|
||||||
where F: Fn() -> Result<String, String> + Send + Sync + 'static {
|
where F: Fn() -> Result<String, String> + Send + Sync + 'static {
|
||||||
SignerService {
|
SignerService {
|
||||||
queue: Arc::new(ConfirmationsQueue::default()),
|
queue: Arc::new(ConfirmationsQueue::default()),
|
||||||
generate_new_token: Box::new(new_token),
|
generate_new_token: Box::new(new_token),
|
||||||
port: port,
|
address: address,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,20 +47,20 @@ impl SignerService {
|
|||||||
self.queue.clone()
|
self.queue.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns signer port (if signer enabled) or `None` otherwise
|
/// Returns signer address (if signer enabled) or `None` otherwise
|
||||||
pub fn port(&self) -> Option<u16> {
|
pub fn address(&self) -> Option<(String, u16)> {
|
||||||
self.port
|
self.address.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if Signer is enabled.
|
/// Returns true if Signer is enabled.
|
||||||
pub fn is_enabled(&self) -> bool {
|
pub fn is_enabled(&self) -> bool {
|
||||||
self.port.is_some()
|
self.address.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
/// Creates new Signer Service for tests.
|
/// Creates new Signer Service for tests.
|
||||||
pub fn new_test(port: Option<u16>) -> Self {
|
pub fn new_test(address: Option<(String, u16)>) -> Self {
|
||||||
SignerService::new(|| Ok("new_token".into()), port)
|
SignerService::new(|| Ok("new_token".into()), address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ pub struct ParityClient<C, M, S: ?Sized> where
|
|||||||
logger: Arc<RotatingLogger>,
|
logger: Arc<RotatingLogger>,
|
||||||
settings: Arc<NetworkSettings>,
|
settings: Arc<NetworkSettings>,
|
||||||
signer: Option<Arc<SignerService>>,
|
signer: Option<Arc<SignerService>>,
|
||||||
|
dapps_interface: Option<String>,
|
||||||
dapps_port: Option<u16>,
|
dapps_port: Option<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,6 +71,7 @@ impl<C, M, S: ?Sized> ParityClient<C, M, S> where
|
|||||||
logger: Arc<RotatingLogger>,
|
logger: Arc<RotatingLogger>,
|
||||||
settings: Arc<NetworkSettings>,
|
settings: Arc<NetworkSettings>,
|
||||||
signer: Option<Arc<SignerService>>,
|
signer: Option<Arc<SignerService>>,
|
||||||
|
dapps_interface: Option<String>,
|
||||||
dapps_port: Option<u16>,
|
dapps_port: Option<u16>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ParityClient {
|
ParityClient {
|
||||||
@ -81,6 +83,7 @@ impl<C, M, S: ?Sized> ParityClient<C, M, S> where
|
|||||||
logger: logger,
|
logger: logger,
|
||||||
settings: settings,
|
settings: settings,
|
||||||
signer: signer,
|
signer: signer,
|
||||||
|
dapps_interface: dapps_interface,
|
||||||
dapps_port: dapps_port,
|
dapps_port: dapps_port,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -261,7 +264,8 @@ impl<C, M, S: ?Sized> Parity for ParityClient<C, M, S> where
|
|||||||
|
|
||||||
self.signer
|
self.signer
|
||||||
.clone()
|
.clone()
|
||||||
.and_then(|signer| signer.port())
|
.and_then(|signer| signer.address())
|
||||||
|
.map(|address| address.1)
|
||||||
.ok_or_else(|| errors::signer_disabled())
|
.ok_or_else(|| errors::signer_disabled())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,6 +276,13 @@ impl<C, M, S: ?Sized> Parity for ParityClient<C, M, S> where
|
|||||||
.ok_or_else(|| errors::dapps_disabled())
|
.ok_or_else(|| errors::dapps_disabled())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dapps_interface(&self) -> Result<String, Error> {
|
||||||
|
try!(self.active());
|
||||||
|
|
||||||
|
self.dapps_interface.clone()
|
||||||
|
.ok_or_else(|| errors::dapps_disabled())
|
||||||
|
}
|
||||||
|
|
||||||
fn next_nonce(&self, address: H160) -> Result<U256, Error> {
|
fn next_nonce(&self, address: H160) -> Result<U256, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
let address: Address = address.into();
|
let address: Address = address.into();
|
||||||
|
@ -38,6 +38,7 @@ pub struct Dependencies {
|
|||||||
pub settings: Arc<NetworkSettings>,
|
pub settings: Arc<NetworkSettings>,
|
||||||
pub network: Arc<ManageNetwork>,
|
pub network: Arc<ManageNetwork>,
|
||||||
pub accounts: Arc<AccountProvider>,
|
pub accounts: Arc<AccountProvider>,
|
||||||
|
pub dapps_interface: Option<String>,
|
||||||
pub dapps_port: Option<u16>,
|
pub dapps_port: Option<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,6 +62,7 @@ impl Dependencies {
|
|||||||
}),
|
}),
|
||||||
network: Arc::new(TestManageNetwork),
|
network: Arc::new(TestManageNetwork),
|
||||||
accounts: Arc::new(AccountProvider::transient_provider()),
|
accounts: Arc::new(AccountProvider::transient_provider()),
|
||||||
|
dapps_interface: Some("127.0.0.1".into()),
|
||||||
dapps_port: Some(18080),
|
dapps_port: Some(18080),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,6 +77,7 @@ impl Dependencies {
|
|||||||
self.logger.clone(),
|
self.logger.clone(),
|
||||||
self.settings.clone(),
|
self.settings.clone(),
|
||||||
signer,
|
signer,
|
||||||
|
self.dapps_interface.clone(),
|
||||||
self.dapps_port,
|
self.dapps_port,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -238,7 +241,7 @@ fn rpc_parity_node_name() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn rpc_parity_unsigned_transactions_count() {
|
fn rpc_parity_unsigned_transactions_count() {
|
||||||
let deps = Dependencies::new();
|
let deps = Dependencies::new();
|
||||||
let io = deps.with_signer(SignerService::new_test(Some(18180)));
|
let io = deps.with_signer(SignerService::new_test(Some(("127.0.0.1".into(), 18180))));
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_unsignedTransactionsCount", "params":[], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "parity_unsignedTransactionsCount", "params":[], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":0,"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":0,"id":1}"#;
|
||||||
@ -282,7 +285,7 @@ fn rpc_parity_encrypt() {
|
|||||||
fn rpc_parity_signer_port() {
|
fn rpc_parity_signer_port() {
|
||||||
// given
|
// given
|
||||||
let deps = Dependencies::new();
|
let deps = Dependencies::new();
|
||||||
let io1 = deps.with_signer(SignerService::new_test(Some(18180)));
|
let io1 = deps.with_signer(SignerService::new_test(Some(("127.0.0.1".into(), 18180))));
|
||||||
let io2 = deps.default_client();
|
let io2 = deps.default_client();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@ -313,6 +316,24 @@ fn rpc_parity_dapps_port() {
|
|||||||
assert_eq!(io2.handle_request_sync(request), Some(response2.to_owned()));
|
assert_eq!(io2.handle_request_sync(request), Some(response2.to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rpc_parity_dapps_interface() {
|
||||||
|
// given
|
||||||
|
let mut deps = Dependencies::new();
|
||||||
|
let io1 = deps.default_client();
|
||||||
|
deps.dapps_interface = None;
|
||||||
|
let io2 = deps.default_client();
|
||||||
|
|
||||||
|
// when
|
||||||
|
let request = r#"{"jsonrpc": "2.0", "method": "parity_dappsInterface", "params": [], "id": 1}"#;
|
||||||
|
let response1 = r#"{"jsonrpc":"2.0","result":"127.0.0.1","id":1}"#;
|
||||||
|
let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32031,"message":"Dapps Server is disabled. This API is not available.","data":null},"id":1}"#;
|
||||||
|
|
||||||
|
// then
|
||||||
|
assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned()));
|
||||||
|
assert_eq!(io2.handle_request_sync(request), Some(response2.to_owned()));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rpc_parity_next_nonce() {
|
fn rpc_parity_next_nonce() {
|
||||||
let deps = Dependencies::new();
|
let deps = Dependencies::new();
|
||||||
|
@ -123,6 +123,10 @@ build_rpc_trait! {
|
|||||||
#[rpc(name = "parity_dappsPort")]
|
#[rpc(name = "parity_dappsPort")]
|
||||||
fn dapps_port(&self) -> Result<u16, Error>;
|
fn dapps_port(&self) -> Result<u16, Error>;
|
||||||
|
|
||||||
|
/// Returns current Dapps Server interface address or an error if dapps server is disabled.
|
||||||
|
#[rpc(name = "parity_dappsInterface")]
|
||||||
|
fn dapps_interface(&self) -> Result<String, Error>;
|
||||||
|
|
||||||
/// Returns next nonce for particular sender. Should include all transactions in the queue.
|
/// Returns next nonce for particular sender. Should include all transactions in the queue.
|
||||||
#[rpc(name = "parity_nextNonce")]
|
#[rpc(name = "parity_nextNonce")]
|
||||||
fn next_nonce(&self, H160) -> Result<U256, Error>;
|
fn next_nonce(&self, H160) -> Result<U256, Error>;
|
||||||
|
Loading…
Reference in New Issue
Block a user