Remove UI related settings from CLI (#8783)
* Remove all ui reference in dapps interface * Pass primary cli build * Add back parity wallet dapp as builtin * Clean up ui settings * Fix all tests in cli * Missed ui files to commit * Add parity-utils endpoint back * Fix non-dapp feature compiling * Inline styles * Remove parity-utils endpoint * Remove ui precompiled crate * Remove parity-ui alltogether * Remove ui feature flags * Move errors to static methods * Fix tests * Remove all reference to utils endpoint and remove server side injection According to https://github.com/paritytech/parity/pull/8539, inject.js is already handled by Parity UI.
This commit is contained in:
parent
114d4433a9
commit
a5190449da
56
Cargo.lock
generated
56
Cargo.lock
generated
@ -2071,8 +2071,6 @@ dependencies = [
|
|||||||
"parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-hash-fetch 1.12.0",
|
"parity-hash-fetch 1.12.0",
|
||||||
"parity-reactor 0.1.0",
|
"parity-reactor 0.1.0",
|
||||||
"parity-ui 1.12.0",
|
|
||||||
"parity-ui-deprecation 1.10.0",
|
|
||||||
"parity-version 1.12.0",
|
"parity-version 1.12.0",
|
||||||
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -2283,56 +2281,6 @@ dependencies = [
|
|||||||
"tokio-uds 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-uds 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parity-ui"
|
|
||||||
version = "1.12.0"
|
|
||||||
dependencies = [
|
|
||||||
"parity-ui-dev 1.9.0 (git+https://github.com/parity-js/shell.git?rev=eecaadcb9e421bce31e91680d14a20bbd38f92a2)",
|
|
||||||
"parity-ui-old-dev 1.9.0 (git+https://github.com/parity-js/dapp-wallet.git?rev=65deb02e7c007a0fd8aab0c089c93e3fd1de6f87)",
|
|
||||||
"parity-ui-old-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-10-wallet.git?rev=4b6f112412716cd05123d32eeb7fda448288a6c6)",
|
|
||||||
"parity-ui-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-10-shell.git?rev=bd25b41cd642c6b822d820dded3aa601a29aa079)",
|
|
||||||
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parity-ui-deprecation"
|
|
||||||
version = "1.10.0"
|
|
||||||
dependencies = [
|
|
||||||
"parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parity-ui-dev"
|
|
||||||
version = "1.9.0"
|
|
||||||
source = "git+https://github.com/parity-js/shell.git?rev=eecaadcb9e421bce31e91680d14a20bbd38f92a2#eecaadcb9e421bce31e91680d14a20bbd38f92a2"
|
|
||||||
dependencies = [
|
|
||||||
"parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parity-ui-old-dev"
|
|
||||||
version = "1.9.0"
|
|
||||||
source = "git+https://github.com/parity-js/dapp-wallet.git?rev=65deb02e7c007a0fd8aab0c089c93e3fd1de6f87#65deb02e7c007a0fd8aab0c089c93e3fd1de6f87"
|
|
||||||
dependencies = [
|
|
||||||
"parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parity-ui-old-precompiled"
|
|
||||||
version = "1.9.0"
|
|
||||||
source = "git+https://github.com/js-dist-paritytech/parity-master-1-10-wallet.git?rev=4b6f112412716cd05123d32eeb7fda448288a6c6#4b6f112412716cd05123d32eeb7fda448288a6c6"
|
|
||||||
dependencies = [
|
|
||||||
"parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parity-ui-precompiled"
|
|
||||||
version = "1.9.0"
|
|
||||||
source = "git+https://github.com/js-dist-paritytech/parity-master-1-10-shell.git?rev=bd25b41cd642c6b822d820dded3aa601a29aa079#bd25b41cd642c6b822d820dded3aa601a29aa079"
|
|
||||||
dependencies = [
|
|
||||||
"parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parity-updater"
|
name = "parity-updater"
|
||||||
version = "1.12.0"
|
version = "1.12.0"
|
||||||
@ -3970,10 +3918,6 @@ dependencies = [
|
|||||||
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
|
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
|
||||||
"checksum parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "261c025c67ba416e9fe63aa9b3236520ce3c74cfbe43590c9cdcec4ccc8180e4"
|
"checksum parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "261c025c67ba416e9fe63aa9b3236520ce3c74cfbe43590c9cdcec4ccc8180e4"
|
||||||
"checksum parity-tokio-ipc 0.1.5 (git+https://github.com/nikvolf/parity-tokio-ipc)" = "<none>"
|
"checksum parity-tokio-ipc 0.1.5 (git+https://github.com/nikvolf/parity-tokio-ipc)" = "<none>"
|
||||||
"checksum parity-ui-dev 1.9.0 (git+https://github.com/parity-js/shell.git?rev=eecaadcb9e421bce31e91680d14a20bbd38f92a2)" = "<none>"
|
|
||||||
"checksum parity-ui-old-dev 1.9.0 (git+https://github.com/parity-js/dapp-wallet.git?rev=65deb02e7c007a0fd8aab0c089c93e3fd1de6f87)" = "<none>"
|
|
||||||
"checksum parity-ui-old-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-10-wallet.git?rev=4b6f112412716cd05123d32eeb7fda448288a6c6)" = "<none>"
|
|
||||||
"checksum parity-ui-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-10-shell.git?rev=bd25b41cd642c6b822d820dded3aa601a29aa079)" = "<none>"
|
|
||||||
"checksum parity-wasm 0.27.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a93ad771f67ce8a6af64c6444a99c07b15f4674203657496fc31244ffb1de2c3"
|
"checksum parity-wasm 0.27.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a93ad771f67ce8a6af64c6444a99c07b15f4674203657496fc31244ffb1de2c3"
|
||||||
"checksum parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0dec124478845b142f68b446cbee953d14d4b41f1bc0425024417720dce693"
|
"checksum parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0dec124478845b142f68b446cbee953d14d4b41f1bc0425024417720dce693"
|
||||||
"checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd"
|
"checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd"
|
||||||
|
11
Cargo.toml
11
Cargo.toml
@ -88,16 +88,7 @@ winapi = { version = "0.3.4", features = ["winsock2", "winuser", "shellapi"] }
|
|||||||
daemonize = { git = "https://github.com/paritytech/daemonize" }
|
daemonize = { git = "https://github.com/paritytech/daemonize" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["ui-precompiled"]
|
default = ["dapps"]
|
||||||
ui = [
|
|
||||||
"ui-enabled",
|
|
||||||
"parity-dapps/ui",
|
|
||||||
]
|
|
||||||
ui-precompiled = [
|
|
||||||
"ui-enabled",
|
|
||||||
"parity-dapps/ui-precompiled",
|
|
||||||
]
|
|
||||||
ui-enabled = ["dapps"]
|
|
||||||
dapps = ["parity-dapps"]
|
dapps = ["parity-dapps"]
|
||||||
json-tests = ["ethcore/json-tests"]
|
json-tests = ["ethcore/json-tests"]
|
||||||
test-heavy = ["ethcore/test-heavy"]
|
test-heavy = ["ethcore/test-heavy"]
|
||||||
|
@ -34,8 +34,6 @@ fetch = { path = "../util/fetch" }
|
|||||||
node-health = { path = "./node-health" }
|
node-health = { path = "./node-health" }
|
||||||
parity-hash-fetch = { path = "../hash-fetch" }
|
parity-hash-fetch = { path = "../hash-fetch" }
|
||||||
parity-reactor = { path = "../util/reactor" }
|
parity-reactor = { path = "../util/reactor" }
|
||||||
parity-ui = { path = "./ui" }
|
|
||||||
parity-ui-deprecation = { path = "./ui-deprecation" }
|
|
||||||
keccak-hash = { path = "../util/hash" }
|
keccak-hash = { path = "../util/hash" }
|
||||||
parity-version = { path = "../util/version" }
|
parity-version = { path = "../util/version" }
|
||||||
registrar = { path = "../registrar" }
|
registrar = { path = "../registrar" }
|
||||||
@ -43,7 +41,3 @@ registrar = { path = "../registrar" }
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
env_logger = "0.4"
|
env_logger = "0.4"
|
||||||
ethcore-devtools = { path = "../devtools" }
|
ethcore-devtools = { path = "../devtools" }
|
||||||
|
|
||||||
[features]
|
|
||||||
ui = ["parity-ui/no-precompiled-js"]
|
|
||||||
ui-precompiled = ["parity-ui/use-precompiled-js"]
|
|
||||||
|
@ -27,7 +27,6 @@ use mime_guess::Mime;
|
|||||||
use apps::manifest::{MANIFEST_FILENAME, deserialize_manifest, serialize_manifest, Manifest};
|
use apps::manifest::{MANIFEST_FILENAME, deserialize_manifest, serialize_manifest, Manifest};
|
||||||
use handlers::{ContentValidator, ValidatorResponse};
|
use handlers::{ContentValidator, ValidatorResponse};
|
||||||
use page::{local, PageCache};
|
use page::{local, PageCache};
|
||||||
use Embeddable;
|
|
||||||
|
|
||||||
type OnDone = Box<Fn(Option<local::Dapp>) + Send>;
|
type OnDone = Box<Fn(Option<local::Dapp>) + Send>;
|
||||||
|
|
||||||
@ -124,17 +123,15 @@ pub struct Dapp {
|
|||||||
id: String,
|
id: String,
|
||||||
dapps_path: PathBuf,
|
dapps_path: PathBuf,
|
||||||
on_done: OnDone,
|
on_done: OnDone,
|
||||||
embeddable_on: Embeddable,
|
|
||||||
pool: CpuPool,
|
pool: CpuPool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dapp {
|
impl Dapp {
|
||||||
pub fn new(id: String, dapps_path: PathBuf, on_done: OnDone, embeddable_on: Embeddable, pool: CpuPool) -> Self {
|
pub fn new(id: String, dapps_path: PathBuf, on_done: OnDone, pool: CpuPool) -> Self {
|
||||||
Dapp {
|
Dapp {
|
||||||
id,
|
id,
|
||||||
dapps_path,
|
dapps_path,
|
||||||
on_done,
|
on_done,
|
||||||
embeddable_on,
|
|
||||||
pool,
|
pool,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,7 +167,6 @@ impl ContentValidator for Dapp {
|
|||||||
fn validate_and_install(self, response: fetch::Response) -> Result<ValidatorResponse, ValidationError> {
|
fn validate_and_install(self, response: fetch::Response) -> Result<ValidatorResponse, ValidationError> {
|
||||||
let id = self.id.clone();
|
let id = self.id.clone();
|
||||||
let pool = self.pool;
|
let pool = self.pool;
|
||||||
let embeddable_on = self.embeddable_on;
|
|
||||||
let validate = move |dapp_path: PathBuf| {
|
let validate = move |dapp_path: PathBuf| {
|
||||||
let (file, zip_path) = write_response_and_check_hash(&id, dapp_path.clone(), &format!("{}.zip", id), response)?;
|
let (file, zip_path) = write_response_and_check_hash(&id, dapp_path.clone(), &format!("{}.zip", id), response)?;
|
||||||
trace!(target: "dapps", "Opening dapp bundle at {:?}", zip_path);
|
trace!(target: "dapps", "Opening dapp bundle at {:?}", zip_path);
|
||||||
@ -210,7 +206,7 @@ impl ContentValidator for Dapp {
|
|||||||
let mut manifest_file = fs::File::create(manifest_path)?;
|
let mut manifest_file = fs::File::create(manifest_path)?;
|
||||||
manifest_file.write_all(manifest_str.as_bytes())?;
|
manifest_file.write_all(manifest_str.as_bytes())?;
|
||||||
// Create endpoint
|
// Create endpoint
|
||||||
let endpoint = local::Dapp::new(pool, dapp_path, manifest.into(), PageCache::Enabled, embeddable_on);
|
let endpoint = local::Dapp::new(pool, dapp_path, manifest.into(), PageCache::Enabled);
|
||||||
Ok(endpoint)
|
Ok(endpoint)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ use hash_fetch::urlhint::{URLHintContract, URLHint, URLHintResult};
|
|||||||
use hyper::StatusCode;
|
use hyper::StatusCode;
|
||||||
|
|
||||||
use ethereum_types::H256;
|
use ethereum_types::H256;
|
||||||
use {Embeddable, SyncStatus, random_filename};
|
use {SyncStatus, random_filename};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use page::local;
|
use page::local;
|
||||||
use handlers::{ContentHandler, ContentFetcherHandler};
|
use handlers::{ContentHandler, ContentFetcherHandler};
|
||||||
@ -50,7 +50,6 @@ pub struct ContentFetcher<F: Fetch = FetchClient, R: URLHint + 'static = URLHint
|
|||||||
resolver: R,
|
resolver: R,
|
||||||
cache: Arc<Mutex<ContentCache>>,
|
cache: Arc<Mutex<ContentCache>>,
|
||||||
sync: Arc<SyncStatus>,
|
sync: Arc<SyncStatus>,
|
||||||
embeddable_on: Embeddable,
|
|
||||||
fetch: F,
|
fetch: F,
|
||||||
pool: CpuPool,
|
pool: CpuPool,
|
||||||
only_content: bool,
|
only_content: bool,
|
||||||
@ -78,7 +77,6 @@ impl<R: URLHint + 'static, F: Fetch> ContentFetcher<F, R> {
|
|||||||
resolver,
|
resolver,
|
||||||
sync,
|
sync,
|
||||||
cache: Arc::new(Mutex::new(ContentCache::default())),
|
cache: Arc::new(Mutex::new(ContentCache::default())),
|
||||||
embeddable_on: None,
|
|
||||||
fetch,
|
fetch,
|
||||||
pool,
|
pool,
|
||||||
only_content: true,
|
only_content: true,
|
||||||
@ -90,38 +88,30 @@ impl<R: URLHint + 'static, F: Fetch> ContentFetcher<F, R> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn embeddable_on(mut self, embeddable_on: Embeddable) -> Self {
|
fn not_found() -> endpoint::Response {
|
||||||
self.embeddable_on = embeddable_on;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn not_found(embeddable: Embeddable) -> endpoint::Response {
|
|
||||||
Box::new(future::ok(ContentHandler::error(
|
Box::new(future::ok(ContentHandler::error(
|
||||||
StatusCode::NotFound,
|
StatusCode::NotFound,
|
||||||
"Resource Not Found",
|
"Resource Not Found",
|
||||||
"Requested resource was not found.",
|
"Requested resource was not found.",
|
||||||
None,
|
None,
|
||||||
embeddable,
|
|
||||||
).into()))
|
).into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn still_syncing(embeddable: Embeddable) -> endpoint::Response {
|
fn still_syncing() -> endpoint::Response {
|
||||||
Box::new(future::ok(ContentHandler::error(
|
Box::new(future::ok(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>"),
|
||||||
embeddable,
|
|
||||||
).into()))
|
).into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dapps_disabled(address: Embeddable) -> endpoint::Response {
|
fn dapps_disabled() -> endpoint::Response {
|
||||||
Box::new(future::ok(ContentHandler::error(
|
Box::new(future::ok(ContentHandler::error(
|
||||||
StatusCode::ServiceUnavailable,
|
StatusCode::ServiceUnavailable,
|
||||||
"Network Dapps Not Available",
|
"Network Dapps Not Available",
|
||||||
"This interface doesn't support network dapps for security reasons.",
|
"This interface doesn't support network dapps for security reasons.",
|
||||||
None,
|
None,
|
||||||
address,
|
|
||||||
).into()))
|
).into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,10 +185,10 @@ impl<R: URLHint + 'static, F: Fetch> Endpoint for ContentFetcher<F, 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_on.clone()))
|
(None, Self::still_syncing())
|
||||||
},
|
},
|
||||||
Some(URLHintResult::Dapp(_)) if self.only_content => {
|
Some(URLHintResult::Dapp(_)) if self.only_content => {
|
||||||
(None, Self::dapps_disabled(self.embeddable_on.clone()))
|
(None, Self::dapps_disabled())
|
||||||
},
|
},
|
||||||
Some(content) => {
|
Some(content) => {
|
||||||
let handler = match content {
|
let handler = match content {
|
||||||
@ -211,10 +201,8 @@ impl<R: URLHint + 'static, F: Fetch> Endpoint for ContentFetcher<F, R> {
|
|||||||
content_id.clone(),
|
content_id.clone(),
|
||||||
self.cache_path.clone(),
|
self.cache_path.clone(),
|
||||||
Box::new(on_done),
|
Box::new(on_done),
|
||||||
self.embeddable_on.clone(),
|
|
||||||
self.pool.clone(),
|
self.pool.clone(),
|
||||||
),
|
),
|
||||||
self.embeddable_on.clone(),
|
|
||||||
self.fetch.clone(),
|
self.fetch.clone(),
|
||||||
self.pool.clone(),
|
self.pool.clone(),
|
||||||
)
|
)
|
||||||
@ -228,10 +216,8 @@ impl<R: URLHint + 'static, F: Fetch> Endpoint for ContentFetcher<F, R> {
|
|||||||
content_id.clone(),
|
content_id.clone(),
|
||||||
self.cache_path.clone(),
|
self.cache_path.clone(),
|
||||||
Box::new(on_done),
|
Box::new(on_done),
|
||||||
self.embeddable_on.clone(),
|
|
||||||
self.pool.clone(),
|
self.pool.clone(),
|
||||||
),
|
),
|
||||||
self.embeddable_on.clone(),
|
|
||||||
self.fetch.clone(),
|
self.fetch.clone(),
|
||||||
self.pool.clone(),
|
self.pool.clone(),
|
||||||
)
|
)
|
||||||
@ -248,7 +234,6 @@ impl<R: URLHint + 'static, F: Fetch> Endpoint for ContentFetcher<F, R> {
|
|||||||
Box::new(on_done),
|
Box::new(on_done),
|
||||||
self.pool.clone(),
|
self.pool.clone(),
|
||||||
),
|
),
|
||||||
self.embeddable_on.clone(),
|
|
||||||
self.fetch.clone(),
|
self.fetch.clone(),
|
||||||
self.pool.clone(),
|
self.pool.clone(),
|
||||||
)
|
)
|
||||||
@ -258,12 +243,12 @@ impl<R: URLHint + 'static, F: Fetch> Endpoint for ContentFetcher<F, R> {
|
|||||||
(Some(ContentStatus::Fetching(handler.fetch_control())), Box::new(handler) as endpoint::Response)
|
(Some(ContentStatus::Fetching(handler.fetch_control())), Box::new(handler) as endpoint::Response)
|
||||||
},
|
},
|
||||||
None if self.sync.is_major_importing() => {
|
None if self.sync.is_major_importing() => {
|
||||||
(None, Self::still_syncing(self.embeddable_on.clone()))
|
(None, Self::still_syncing())
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
// This may happen when sync status changes in between
|
// This may happen when sync status changes in between
|
||||||
// `contains` and `to_handler`
|
// `contains` and `to_handler`
|
||||||
(None, Self::not_found(self.embeddable_on.clone()))
|
(None, Self::not_found())
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -330,7 +315,7 @@ mod tests {
|
|||||||
icon_url: "".into(),
|
icon_url: "".into(),
|
||||||
local_url: Some("".into()),
|
local_url: Some("".into()),
|
||||||
allow_js_eval: None,
|
allow_js_eval: None,
|
||||||
}, Default::default(), None);
|
}, Default::default());
|
||||||
|
|
||||||
// when
|
// when
|
||||||
fetcher.set_status("test", ContentStatus::Ready(handler));
|
fetcher.set_status("test", ContentStatus::Ready(handler));
|
||||||
|
@ -24,7 +24,6 @@ use futures_cpupool::CpuPool;
|
|||||||
use apps::manifest::{MANIFEST_FILENAME, deserialize_manifest};
|
use apps::manifest::{MANIFEST_FILENAME, deserialize_manifest};
|
||||||
use endpoint::{Endpoint, EndpointInfo};
|
use endpoint::{Endpoint, EndpointInfo};
|
||||||
use page::{local, PageCache};
|
use page::{local, PageCache};
|
||||||
use Embeddable;
|
|
||||||
|
|
||||||
struct LocalDapp {
|
struct LocalDapp {
|
||||||
id: String,
|
id: String,
|
||||||
@ -65,14 +64,14 @@ fn read_manifest(name: &str, mut path: PathBuf) -> EndpointInfo {
|
|||||||
/// Returns Dapp Id and Local Dapp Endpoint for given filesystem path.
|
/// Returns Dapp Id and Local Dapp Endpoint for given filesystem path.
|
||||||
/// Parses the path to extract last component (for name).
|
/// Parses the path to extract last component (for name).
|
||||||
/// `None` is returned when path is invalid or non-existent.
|
/// `None` is returned when path is invalid or non-existent.
|
||||||
pub fn local_endpoint<P: AsRef<Path>>(path: P, embeddable: Embeddable, pool: CpuPool) -> Option<(String, Box<local::Dapp>)> {
|
pub fn local_endpoint<P: AsRef<Path>>(path: P, pool: CpuPool) -> Option<(String, Box<local::Dapp>)> {
|
||||||
let path = path.as_ref().to_owned();
|
let path = path.as_ref().to_owned();
|
||||||
path.canonicalize().ok().and_then(|path| {
|
path.canonicalize().ok().and_then(|path| {
|
||||||
let name = path.file_name().and_then(|name| name.to_str());
|
let name = path.file_name().and_then(|name| name.to_str());
|
||||||
name.map(|name| {
|
name.map(|name| {
|
||||||
let dapp = local_dapp(name.into(), path.clone());
|
let dapp = local_dapp(name.into(), path.clone());
|
||||||
(dapp.id, Box::new(local::Dapp::new(
|
(dapp.id, Box::new(local::Dapp::new(
|
||||||
pool.clone(), dapp.path, dapp.info, PageCache::Disabled, embeddable.clone())
|
pool.clone(), dapp.path, dapp.info, PageCache::Disabled)
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -90,12 +89,12 @@ fn local_dapp(name: String, path: PathBuf) -> LocalDapp {
|
|||||||
|
|
||||||
/// Returns endpoints for Local Dapps found for given filesystem path.
|
/// Returns endpoints for Local Dapps found for given filesystem path.
|
||||||
/// Scans the directory and collects `local::Dapp`.
|
/// Scans the directory and collects `local::Dapp`.
|
||||||
pub fn local_endpoints<P: AsRef<Path>>(dapps_path: P, embeddable: Embeddable, pool: CpuPool) -> BTreeMap<String, Box<Endpoint>> {
|
pub fn local_endpoints<P: AsRef<Path>>(dapps_path: P, pool: CpuPool) -> BTreeMap<String, Box<Endpoint>> {
|
||||||
let mut pages = BTreeMap::<String, Box<Endpoint>>::new();
|
let mut pages = BTreeMap::<String, Box<Endpoint>>::new();
|
||||||
for dapp in local_dapps(dapps_path.as_ref()) {
|
for dapp in local_dapps(dapps_path.as_ref()) {
|
||||||
pages.insert(
|
pages.insert(
|
||||||
dapp.id,
|
dapp.id,
|
||||||
Box::new(local::Dapp::new(pool.clone(), dapp.path, dapp.info, PageCache::Disabled, embeddable.clone()))
|
Box::new(local::Dapp::new(pool.clone(), dapp.path, dapp.info, PageCache::Disabled))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
pages
|
pages
|
||||||
|
@ -17,17 +17,15 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use endpoint::{Endpoints, Endpoint};
|
use endpoint::Endpoints;
|
||||||
use futures_cpupool::CpuPool;
|
use futures_cpupool::CpuPool;
|
||||||
use page;
|
|
||||||
use proxypac::ProxyPac;
|
use proxypac::ProxyPac;
|
||||||
use web::Web;
|
use web::Web;
|
||||||
use fetch::Fetch;
|
use fetch::Fetch;
|
||||||
use {WebProxyTokens, ParentFrameSettings};
|
use WebProxyTokens;
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod cache;
|
mod cache;
|
||||||
mod ui;
|
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
pub mod fetcher;
|
pub mod fetcher;
|
||||||
pub mod manifest;
|
pub mod manifest;
|
||||||
@ -37,68 +35,35 @@ pub use self::app::App;
|
|||||||
pub const HOME_PAGE: &'static str = "home";
|
pub const HOME_PAGE: &'static str = "home";
|
||||||
pub const RPC_PATH: &'static str = "rpc";
|
pub const RPC_PATH: &'static str = "rpc";
|
||||||
pub const API_PATH: &'static str = "api";
|
pub const API_PATH: &'static str = "api";
|
||||||
pub const UTILS_PATH: &'static str = "parity-utils";
|
|
||||||
pub const WEB_PATH: &'static str = "web";
|
pub const WEB_PATH: &'static str = "web";
|
||||||
pub const URL_REFERER: &'static str = "__referer=";
|
pub const URL_REFERER: &'static str = "__referer=";
|
||||||
|
|
||||||
pub fn utils(pool: CpuPool) -> Box<Endpoint> {
|
|
||||||
Box::new(page::builtin::Dapp::new(pool, ::parity_ui::App::default()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ui(pool: CpuPool) -> Box<Endpoint> {
|
|
||||||
Box::new(page::builtin::Dapp::with_fallback_to_index(pool, ::parity_ui::App::default()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ui_deprecation(pool: CpuPool) -> Box<Endpoint> {
|
|
||||||
Box::new(page::builtin::Dapp::with_fallback_to_index(pool, ::parity_ui_deprecation::App::default()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ui_redirection(embeddable: Option<ParentFrameSettings>) -> Box<Endpoint> {
|
|
||||||
Box::new(ui::Redirection::new(embeddable))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn all_endpoints<F: Fetch>(
|
pub fn all_endpoints<F: Fetch>(
|
||||||
dapps_path: PathBuf,
|
dapps_path: PathBuf,
|
||||||
extra_dapps: Vec<PathBuf>,
|
extra_dapps: Vec<PathBuf>,
|
||||||
dapps_domain: &str,
|
dapps_domain: &str,
|
||||||
embeddable: Option<ParentFrameSettings>,
|
|
||||||
web_proxy_tokens: Arc<WebProxyTokens>,
|
web_proxy_tokens: Arc<WebProxyTokens>,
|
||||||
fetch: F,
|
fetch: F,
|
||||||
pool: CpuPool,
|
pool: CpuPool,
|
||||||
) -> (Vec<String>, Endpoints) {
|
) -> (Vec<String>, 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.clone(), embeddable.clone(), pool.clone());
|
let mut pages = fs::local_endpoints(dapps_path.clone(), pool.clone());
|
||||||
let local_endpoints: Vec<String> = pages.keys().cloned().collect();
|
let local_endpoints: Vec<String> = pages.keys().cloned().collect();
|
||||||
for path in extra_dapps {
|
for path in extra_dapps {
|
||||||
if let Some((id, endpoint)) = fs::local_endpoint(path.clone(), embeddable.clone(), pool.clone()) {
|
if let Some((id, endpoint)) = fs::local_endpoint(path.clone(), pool.clone()) {
|
||||||
pages.insert(id, endpoint);
|
pages.insert(id, endpoint);
|
||||||
} else {
|
} else {
|
||||||
warn!(target: "dapps", "Ignoring invalid dapp at {}", path.display());
|
warn!(target: "dapps", "Ignoring invalid dapp at {}", path.display());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE [ToDr] Dapps will be currently embeded on 8180
|
|
||||||
pages.insert(
|
|
||||||
"ui".into(),
|
|
||||||
Box::new(page::builtin::Dapp::new_safe_to_embed(pool.clone(), ::parity_ui::App::default(), embeddable.clone()))
|
|
||||||
);
|
|
||||||
// old version
|
|
||||||
pages.insert(
|
|
||||||
"v1".into(),
|
|
||||||
Box::new({
|
|
||||||
let mut page = page::builtin::Dapp::new_safe_to_embed(pool.clone(), ::parity_ui::old::App::default(), embeddable.clone());
|
|
||||||
// allow JS eval on old Wallet
|
|
||||||
page.allow_js_eval();
|
|
||||||
page
|
|
||||||
})
|
|
||||||
);
|
|
||||||
pages.insert(
|
pages.insert(
|
||||||
"proxy".into(),
|
"proxy".into(),
|
||||||
ProxyPac::boxed(embeddable.clone(), dapps_domain.to_owned())
|
ProxyPac::boxed(dapps_domain.to_owned())
|
||||||
);
|
);
|
||||||
pages.insert(
|
pages.insert(
|
||||||
WEB_PATH.into(),
|
WEB_PATH.into(),
|
||||||
Web::boxed(embeddable.clone(), web_proxy_tokens.clone(), fetch.clone(), pool.clone())
|
Web::boxed(web_proxy_tokens.clone(), fetch.clone(), pool.clone())
|
||||||
);
|
);
|
||||||
|
|
||||||
(local_endpoints, pages)
|
(local_endpoints, pages)
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is part of Parity.
|
|
||||||
|
|
||||||
// Parity is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// Parity is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
//! UI redirections
|
|
||||||
|
|
||||||
use hyper::StatusCode;
|
|
||||||
use futures::future;
|
|
||||||
|
|
||||||
use endpoint::{Endpoint, Request, Response, EndpointPath};
|
|
||||||
use {handlers, Embeddable};
|
|
||||||
|
|
||||||
/// Redirection to UI server.
|
|
||||||
pub struct Redirection {
|
|
||||||
embeddable_on: Embeddable,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Redirection {
|
|
||||||
pub fn new(
|
|
||||||
embeddable_on: Embeddable,
|
|
||||||
) -> Self {
|
|
||||||
Redirection {
|
|
||||||
embeddable_on,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Endpoint for Redirection {
|
|
||||||
fn respond(&self, _path: EndpointPath, req: Request) -> Response {
|
|
||||||
Box::new(future::ok(if let Some(ref frame) = self.embeddable_on {
|
|
||||||
trace!(target: "dapps", "Redirecting to signer interface.");
|
|
||||||
let protocol = req.uri().scheme().unwrap_or("http");
|
|
||||||
handlers::Redirection::new(format!("{}://{}:{}", protocol, &frame.host, frame.port)).into()
|
|
||||||
} else {
|
|
||||||
trace!(target: "dapps", "Signer disabled, returning 404.");
|
|
||||||
handlers::ContentHandler::error(
|
|
||||||
StatusCode::NotFound,
|
|
||||||
"404 Not Found",
|
|
||||||
"Your homepage is not available when Trusted Signer is disabled.",
|
|
||||||
Some("You can still access dapps by writing a correct address, though. Re-enable Signer to get your homepage back."),
|
|
||||||
None,
|
|
||||||
).into()
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,7 +4,88 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<title>{title}</title>
|
<title>{title}</title>
|
||||||
<link rel="stylesheet" href="/parity-utils/styles.css">
|
<style>
|
||||||
|
:root, :root body {{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
font-size: 100%;
|
||||||
|
font: inherit;
|
||||||
|
vertical-align: baseline;
|
||||||
|
background: rgb(95, 95, 95);
|
||||||
|
color: rgba(255, 255, 255, 0.75);
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-weight: 300;
|
||||||
|
}}
|
||||||
|
|
||||||
|
:root a, :root a:visited {{
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
color: rgb(0, 151, 167); /* #f80 */
|
||||||
|
}}
|
||||||
|
|
||||||
|
:root a:hover {{
|
||||||
|
color: rgb(0, 174, 193);
|
||||||
|
}}
|
||||||
|
|
||||||
|
h1,h2,h3,h4,h5,h6 {{
|
||||||
|
font-weight: 300;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-decoration: none;
|
||||||
|
}}
|
||||||
|
|
||||||
|
h1 {{
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: 36px;
|
||||||
|
color: rgb(0, 151, 167);
|
||||||
|
}}
|
||||||
|
|
||||||
|
h2 {{
|
||||||
|
font-size: 20px;
|
||||||
|
line-height: 34px;
|
||||||
|
}}
|
||||||
|
|
||||||
|
code,kbd,pre,samp {{
|
||||||
|
font-family: monospace;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.parity-navbar {{
|
||||||
|
background: rgb(65, 65, 65);
|
||||||
|
height: 72px;
|
||||||
|
padding: 0 1rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.parity-status {{
|
||||||
|
clear: both;
|
||||||
|
padding: 1rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
text-align: right;
|
||||||
|
opacity: 0.75;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.parity-box {{
|
||||||
|
margin: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
background-color: rgb(48, 48, 48);
|
||||||
|
box-sizing: border-box;
|
||||||
|
box-shadow: rgba(0, 0, 0, 0.117647) 0px 1px 6px, rgba(0, 0, 0, 0.117647) 0px 1px 4px;
|
||||||
|
border-radius: 2px;
|
||||||
|
z-index: 1;
|
||||||
|
color: #aaa;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.parity-box h1,
|
||||||
|
.parity-box h2,
|
||||||
|
.parity-box h3,
|
||||||
|
.parity-box h4,
|
||||||
|
.parity-box h5,
|
||||||
|
.parity-box h6 {{
|
||||||
|
margin: 0;
|
||||||
|
}}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="parity-navbar">
|
<div class="parity-navbar">
|
||||||
|
@ -22,14 +22,12 @@ use hyper::StatusCode;
|
|||||||
use parity_version::version;
|
use parity_version::version;
|
||||||
|
|
||||||
use handlers::add_security_headers;
|
use handlers::add_security_headers;
|
||||||
use Embeddable;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ContentHandler {
|
pub struct ContentHandler {
|
||||||
code: StatusCode,
|
code: StatusCode,
|
||||||
content: String,
|
content: String,
|
||||||
mimetype: mime::Mime,
|
mimetype: mime::Mime,
|
||||||
safe_to_embed_on: Embeddable,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ContentHandler {
|
impl ContentHandler {
|
||||||
@ -37,8 +35,8 @@ impl ContentHandler {
|
|||||||
Self::new(StatusCode::Ok, content, mimetype)
|
Self::new(StatusCode::Ok, content, mimetype)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn html(code: StatusCode, content: String, embeddable_on: Embeddable) -> Self {
|
pub fn html(code: StatusCode, content: String) -> Self {
|
||||||
Self::new_embeddable(code, content, mime::TEXT_HTML, embeddable_on)
|
Self::new(code, content, mime::TEXT_HTML)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error(
|
pub fn error(
|
||||||
@ -46,7 +44,6 @@ impl ContentHandler {
|
|||||||
title: &str,
|
title: &str,
|
||||||
message: &str,
|
message: &str,
|
||||||
details: Option<&str>,
|
details: Option<&str>,
|
||||||
embeddable_on: Embeddable,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::html(code, format!(
|
Self::html(code, format!(
|
||||||
include_str!("../error_tpl.html"),
|
include_str!("../error_tpl.html"),
|
||||||
@ -54,24 +51,18 @@ impl ContentHandler {
|
|||||||
message=message,
|
message=message,
|
||||||
details=details.unwrap_or_else(|| ""),
|
details=details.unwrap_or_else(|| ""),
|
||||||
version=version(),
|
version=version(),
|
||||||
), embeddable_on)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(code: StatusCode, content: String, mimetype: mime::Mime) -> Self {
|
pub fn new(
|
||||||
Self::new_embeddable(code, content, mimetype, None)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_embeddable(
|
|
||||||
code: StatusCode,
|
code: StatusCode,
|
||||||
content: String,
|
content: String,
|
||||||
mimetype: mime::Mime,
|
mimetype: mime::Mime,
|
||||||
safe_to_embed_on: Embeddable,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ContentHandler {
|
ContentHandler {
|
||||||
code,
|
code,
|
||||||
content,
|
content,
|
||||||
mimetype,
|
mimetype,
|
||||||
safe_to_embed_on,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,7 +73,7 @@ impl Into<hyper::Response> for ContentHandler {
|
|||||||
.with_status(self.code)
|
.with_status(self.code)
|
||||||
.with_header(header::ContentType(self.mimetype))
|
.with_header(header::ContentType(self.mimetype))
|
||||||
.with_body(self.content);
|
.with_body(self.content);
|
||||||
add_security_headers(&mut res.headers_mut(), self.safe_to_embed_on, false);
|
add_security_headers(&mut res.headers_mut(), false);
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ impl Into<hyper::Response> for EchoHandler {
|
|||||||
.with_header(content_type.unwrap_or(header::ContentType::json()))
|
.with_header(content_type.unwrap_or(header::ContentType::json()))
|
||||||
.with_body(self.request.body());
|
.with_body(self.request.body());
|
||||||
|
|
||||||
add_security_headers(res.headers_mut(), None, false);
|
add_security_headers(res.headers_mut(), false);
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
66
dapps/src/handlers/errors.rs
Normal file
66
dapps/src/handlers/errors.rs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Handler errors.
|
||||||
|
|
||||||
|
use handlers::{ContentHandler, FETCH_TIMEOUT};
|
||||||
|
use hyper::StatusCode;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
pub fn streaming() -> ContentHandler {
|
||||||
|
ContentHandler::error(
|
||||||
|
StatusCode::BadGateway,
|
||||||
|
"Streaming Error",
|
||||||
|
"This content is being streamed in other place.",
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn download_error<E: fmt::Debug>(e: E) -> ContentHandler {
|
||||||
|
ContentHandler::error(
|
||||||
|
StatusCode::BadGateway,
|
||||||
|
"Download Error",
|
||||||
|
"There was an error when fetching the content.",
|
||||||
|
Some(&format!("{:?}", e)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn invalid_content<E: fmt::Debug>(e: E) -> ContentHandler {
|
||||||
|
ContentHandler::error(
|
||||||
|
StatusCode::BadGateway,
|
||||||
|
"Invalid Dapp",
|
||||||
|
"Downloaded bundle does not contain a valid content.",
|
||||||
|
Some(&format!("{:?}", e)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn timeout_error() -> ContentHandler {
|
||||||
|
ContentHandler::error(
|
||||||
|
StatusCode::GatewayTimeout,
|
||||||
|
"Download Timeout",
|
||||||
|
&format!("Could not fetch content within {} seconds.", FETCH_TIMEOUT.as_secs()),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn method_not_allowed() -> ContentHandler {
|
||||||
|
ContentHandler::error(
|
||||||
|
StatusCode::MethodNotAllowed,
|
||||||
|
"Method Not Allowed",
|
||||||
|
"Only <code>GET</code> requests are allowed.",
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
@ -19,20 +19,17 @@
|
|||||||
use std::{fmt, mem};
|
use std::{fmt, mem};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::time::{Instant, Duration};
|
use std::time::Instant;
|
||||||
use fetch::{self, Fetch};
|
use fetch::{self, Fetch};
|
||||||
use futures::sync::oneshot;
|
use futures::sync::oneshot;
|
||||||
use futures::{self, Future};
|
use futures::{self, Future};
|
||||||
use futures_cpupool::CpuPool;
|
use futures_cpupool::CpuPool;
|
||||||
use hyper::{self, StatusCode};
|
use hyper;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
use endpoint::{self, EndpointPath};
|
use endpoint::{self, EndpointPath};
|
||||||
use handlers::{ContentHandler, StreamingHandler};
|
use handlers::{ContentHandler, StreamingHandler, FETCH_TIMEOUT, errors};
|
||||||
use page::local;
|
use page::local;
|
||||||
use {Embeddable};
|
|
||||||
|
|
||||||
const FETCH_TIMEOUT: Duration = Duration::from_secs(300);
|
|
||||||
|
|
||||||
pub enum ValidatorResponse {
|
pub enum ValidatorResponse {
|
||||||
Local(local::Dapp),
|
Local(local::Dapp),
|
||||||
@ -134,8 +131,7 @@ impl Future for WaitingHandler {
|
|||||||
return Ok(futures::Async::Ready(handler.into()));
|
return Ok(futures::Async::Ready(handler.into()));
|
||||||
},
|
},
|
||||||
WaitResult::NonAwaitable => {
|
WaitResult::NonAwaitable => {
|
||||||
let errors = Errors { embeddable_on: None };
|
return Ok(futures::Async::Ready(errors::streaming().into()));
|
||||||
return Ok(futures::Async::Ready(errors.streaming().into()));
|
|
||||||
},
|
},
|
||||||
WaitResult::Done(endpoint) => {
|
WaitResult::Done(endpoint) => {
|
||||||
WaitState::Done(endpoint.to_response(&self.path).into())
|
WaitState::Done(endpoint.to_response(&self.path).into())
|
||||||
@ -152,63 +148,6 @@ impl Future for WaitingHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct Errors {
|
|
||||||
embeddable_on: Embeddable,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Errors {
|
|
||||||
fn streaming(&self) -> ContentHandler {
|
|
||||||
ContentHandler::error(
|
|
||||||
StatusCode::BadGateway,
|
|
||||||
"Streaming Error",
|
|
||||||
"This content is being streamed in other place.",
|
|
||||||
None,
|
|
||||||
self.embeddable_on.clone(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn download_error<E: fmt::Debug>(&self, e: E) -> ContentHandler {
|
|
||||||
ContentHandler::error(
|
|
||||||
StatusCode::BadGateway,
|
|
||||||
"Download Error",
|
|
||||||
"There was an error when fetching the content.",
|
|
||||||
Some(&format!("{:?}", e)),
|
|
||||||
self.embeddable_on.clone(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn invalid_content<E: fmt::Debug>(&self, e: E) -> ContentHandler {
|
|
||||||
ContentHandler::error(
|
|
||||||
StatusCode::BadGateway,
|
|
||||||
"Invalid Dapp",
|
|
||||||
"Downloaded bundle does not contain a valid content.",
|
|
||||||
Some(&format!("{:?}", e)),
|
|
||||||
self.embeddable_on.clone(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn timeout_error(&self) -> ContentHandler {
|
|
||||||
ContentHandler::error(
|
|
||||||
StatusCode::GatewayTimeout,
|
|
||||||
"Download Timeout",
|
|
||||||
&format!("Could not fetch content within {} seconds.", FETCH_TIMEOUT.as_secs()),
|
|
||||||
None,
|
|
||||||
self.embeddable_on.clone(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn method_not_allowed(&self) -> ContentHandler {
|
|
||||||
ContentHandler::error(
|
|
||||||
StatusCode::MethodNotAllowed,
|
|
||||||
"Method Not Allowed",
|
|
||||||
"Only <code>GET</code> requests are allowed.",
|
|
||||||
None,
|
|
||||||
self.embeddable_on.clone(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum FetchState {
|
enum FetchState {
|
||||||
Error(ContentHandler),
|
Error(ContentHandler),
|
||||||
InProgress(Box<Future<Item=FetchState, Error=()> + Send>),
|
InProgress(Box<Future<Item=FetchState, Error=()> + Send>),
|
||||||
@ -237,7 +176,6 @@ impl fmt::Debug for FetchState {
|
|||||||
pub struct ContentFetcherHandler {
|
pub struct ContentFetcherHandler {
|
||||||
fetch_control: FetchControl,
|
fetch_control: FetchControl,
|
||||||
status: FetchState,
|
status: FetchState,
|
||||||
errors: Errors,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ContentFetcherHandler {
|
impl ContentFetcherHandler {
|
||||||
@ -250,12 +188,10 @@ impl ContentFetcherHandler {
|
|||||||
url: &str,
|
url: &str,
|
||||||
path: EndpointPath,
|
path: EndpointPath,
|
||||||
installer: H,
|
installer: H,
|
||||||
embeddable_on: Embeddable,
|
|
||||||
fetch: F,
|
fetch: F,
|
||||||
pool: CpuPool,
|
pool: CpuPool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let fetch_control = FetchControl::default();
|
let fetch_control = FetchControl::default();
|
||||||
let errors = Errors { embeddable_on };
|
|
||||||
|
|
||||||
// Validation of method
|
// Validation of method
|
||||||
let status = match *method {
|
let status = match *method {
|
||||||
@ -268,18 +204,16 @@ impl ContentFetcherHandler {
|
|||||||
url,
|
url,
|
||||||
fetch_control.abort.clone(),
|
fetch_control.abort.clone(),
|
||||||
path,
|
path,
|
||||||
errors.clone(),
|
|
||||||
installer,
|
installer,
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
// or return error
|
// or return error
|
||||||
_ => FetchState::Error(errors.method_not_allowed()),
|
_ => FetchState::Error(errors::method_not_allowed()),
|
||||||
};
|
};
|
||||||
|
|
||||||
ContentFetcherHandler {
|
ContentFetcherHandler {
|
||||||
fetch_control,
|
fetch_control,
|
||||||
status,
|
status,
|
||||||
errors,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,7 +223,6 @@ impl ContentFetcherHandler {
|
|||||||
url: &str,
|
url: &str,
|
||||||
abort: Arc<AtomicBool>,
|
abort: Arc<AtomicBool>,
|
||||||
path: EndpointPath,
|
path: EndpointPath,
|
||||||
errors: Errors,
|
|
||||||
installer: H,
|
installer: H,
|
||||||
) -> Box<Future<Item=FetchState, Error=()> + Send> {
|
) -> Box<Future<Item=FetchState, Error=()> + Send> {
|
||||||
// Start fetching the content
|
// Start fetching the content
|
||||||
@ -311,12 +244,12 @@ impl ContentFetcherHandler {
|
|||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
trace!(target: "dapps", "Error while validating content: {:?}", e);
|
trace!(target: "dapps", "Error while validating content: {:?}", e);
|
||||||
FetchState::Error(errors.invalid_content(e))
|
FetchState::Error(errors::invalid_content(e))
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(target: "dapps", "Unable to fetch content: {:?}", e);
|
warn!(target: "dapps", "Unable to fetch content: {:?}", e);
|
||||||
FetchState::Error(errors.download_error(e))
|
FetchState::Error(errors::download_error(e))
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@ -347,7 +280,7 @@ impl Future for ContentFetcherHandler {
|
|||||||
// Request may time out
|
// Request may time out
|
||||||
FetchState::InProgress(_) if self.fetch_control.is_deadline_reached() => {
|
FetchState::InProgress(_) if self.fetch_control.is_deadline_reached() => {
|
||||||
trace!(target: "dapps", "Fetching dapp failed because of timeout.");
|
trace!(target: "dapps", "Fetching dapp failed because of timeout.");
|
||||||
FetchState::Error(self.errors.timeout_error())
|
FetchState::Error(errors::timeout_error())
|
||||||
},
|
},
|
||||||
FetchState::InProgress(ref mut receiver) => {
|
FetchState::InProgress(ref mut receiver) => {
|
||||||
// Check if there is a response
|
// Check if there is a response
|
||||||
|
@ -22,6 +22,7 @@ mod fetch;
|
|||||||
mod reader;
|
mod reader;
|
||||||
mod redirect;
|
mod redirect;
|
||||||
mod streaming;
|
mod streaming;
|
||||||
|
mod errors;
|
||||||
|
|
||||||
pub use self::content::ContentHandler;
|
pub use self::content::ContentHandler;
|
||||||
pub use self::echo::EchoHandler;
|
pub use self::echo::EchoHandler;
|
||||||
@ -30,20 +31,16 @@ pub use self::reader::Reader;
|
|||||||
pub use self::redirect::Redirection;
|
pub use self::redirect::Redirection;
|
||||||
pub use self::streaming::StreamingHandler;
|
pub use self::streaming::StreamingHandler;
|
||||||
|
|
||||||
use std::iter;
|
|
||||||
use itertools::Itertools;
|
|
||||||
use hyper::header;
|
use hyper::header;
|
||||||
use {apps, address, Embeddable};
|
use std::time::Duration;
|
||||||
|
|
||||||
|
const FETCH_TIMEOUT: Duration = Duration::from_secs(300);
|
||||||
|
|
||||||
/// Adds security-related headers to the Response.
|
/// Adds security-related headers to the Response.
|
||||||
pub fn add_security_headers(headers: &mut header::Headers, embeddable_on: Embeddable, allow_js_eval: bool) {
|
pub fn add_security_headers(headers: &mut header::Headers, allow_js_eval: bool) {
|
||||||
headers.set_raw("X-XSS-Protection", "1; mode=block");
|
headers.set_raw("X-XSS-Protection", "1; mode=block");
|
||||||
headers.set_raw("X-Content-Type-Options", "nosniff");
|
headers.set_raw("X-Content-Type-Options", "nosniff");
|
||||||
|
|
||||||
// Embedding header:
|
|
||||||
if let None = embeddable_on {
|
|
||||||
headers.set_raw("X-Frame-Options", "SAMEORIGIN");
|
headers.set_raw("X-Frame-Options", "SAMEORIGIN");
|
||||||
}
|
|
||||||
|
|
||||||
// Content Security Policy headers
|
// Content Security Policy headers
|
||||||
headers.set_raw("Content-Security-Policy", String::new()
|
headers.set_raw("Content-Security-Policy", String::new()
|
||||||
@ -70,11 +67,7 @@ pub fn add_security_headers(headers: &mut header::Headers, embeddable_on: Embedd
|
|||||||
+ "object-src 'none';"
|
+ "object-src 'none';"
|
||||||
// Allow scripts
|
// Allow scripts
|
||||||
+ {
|
+ {
|
||||||
let script_src = embeddable_on.as_ref()
|
let script_src = "";
|
||||||
.map(|e| e.extra_script_src.iter()
|
|
||||||
.map(|&(ref host, port)| address(host, port))
|
|
||||||
.join(" ")
|
|
||||||
).unwrap_or_default();
|
|
||||||
let eval = if allow_js_eval { " 'unsafe-eval'" } else { "" };
|
let eval = if allow_js_eval { " 'unsafe-eval'" } else { "" };
|
||||||
|
|
||||||
&format!(
|
&format!(
|
||||||
@ -93,29 +86,6 @@ pub fn add_security_headers(headers: &mut header::Headers, embeddable_on: Embedd
|
|||||||
// Never allow mixed content
|
// Never allow mixed content
|
||||||
+ "block-all-mixed-content;"
|
+ "block-all-mixed-content;"
|
||||||
// Specify if the site can be embedded.
|
// Specify if the site can be embedded.
|
||||||
+ &match embeddable_on {
|
+ "frame-ancestors 'self';"
|
||||||
Some(ref embed) => {
|
|
||||||
let std = address(&embed.host, embed.port);
|
|
||||||
let proxy = format!("{}.{}", apps::HOME_PAGE, embed.dapps_domain);
|
|
||||||
let domain = format!("*.{}:{}", embed.dapps_domain, embed.port);
|
|
||||||
|
|
||||||
let mut ancestors = vec![std, domain, proxy]
|
|
||||||
.into_iter()
|
|
||||||
.chain(embed.extra_embed_on
|
|
||||||
.iter()
|
|
||||||
.map(|&(ref host, port)| address(host, port))
|
|
||||||
);
|
|
||||||
|
|
||||||
let ancestors = if embed.host == "127.0.0.1" {
|
|
||||||
let localhost = address("localhost", embed.port);
|
|
||||||
ancestors.chain(iter::once(localhost)).join(" ")
|
|
||||||
} else {
|
|
||||||
ancestors.join(" ")
|
|
||||||
};
|
|
||||||
|
|
||||||
format!("frame-ancestors {};", ancestors)
|
|
||||||
},
|
|
||||||
None => format!("frame-ancestors 'self';"),
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -20,24 +20,21 @@ use std::io;
|
|||||||
use hyper::{self, header, mime, StatusCode};
|
use hyper::{self, header, mime, StatusCode};
|
||||||
|
|
||||||
use handlers::{add_security_headers, Reader};
|
use handlers::{add_security_headers, Reader};
|
||||||
use Embeddable;
|
|
||||||
|
|
||||||
pub struct StreamingHandler<R> {
|
pub struct StreamingHandler<R> {
|
||||||
initial: Vec<u8>,
|
initial: Vec<u8>,
|
||||||
content: R,
|
content: R,
|
||||||
status: StatusCode,
|
status: StatusCode,
|
||||||
mimetype: mime::Mime,
|
mimetype: mime::Mime,
|
||||||
safe_to_embed_on: Embeddable,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: io::Read> StreamingHandler<R> {
|
impl<R: io::Read> StreamingHandler<R> {
|
||||||
pub fn new(content: R, status: StatusCode, mimetype: mime::Mime, safe_to_embed_on: Embeddable) -> Self {
|
pub fn new(content: R, status: StatusCode, mimetype: mime::Mime) -> Self {
|
||||||
StreamingHandler {
|
StreamingHandler {
|
||||||
initial: Vec::new(),
|
initial: Vec::new(),
|
||||||
content,
|
content,
|
||||||
status,
|
status,
|
||||||
mimetype,
|
mimetype,
|
||||||
safe_to_embed_on,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +48,7 @@ impl<R: io::Read> StreamingHandler<R> {
|
|||||||
.with_status(self.status)
|
.with_status(self.status)
|
||||||
.with_header(header::ContentType(self.mimetype))
|
.with_header(header::ContentType(self.mimetype))
|
||||||
.with_body(body);
|
.with_body(body);
|
||||||
add_security_headers(&mut res.headers_mut(), self.safe_to_embed_on, false);
|
add_security_headers(&mut res.headers_mut(), false);
|
||||||
|
|
||||||
(reader, res)
|
(reader, res)
|
||||||
}
|
}
|
||||||
|
119
dapps/src/lib.rs
119
dapps/src/lib.rs
@ -38,8 +38,6 @@ extern crate fetch;
|
|||||||
extern crate node_health;
|
extern crate node_health;
|
||||||
extern crate parity_dapps_glue as parity_dapps;
|
extern crate parity_dapps_glue as parity_dapps;
|
||||||
extern crate parity_hash_fetch as hash_fetch;
|
extern crate parity_hash_fetch as hash_fetch;
|
||||||
extern crate parity_ui;
|
|
||||||
extern crate parity_ui_deprecation;
|
|
||||||
extern crate keccak_hash as hash;
|
extern crate keccak_hash as hash;
|
||||||
extern crate parity_version;
|
extern crate parity_version;
|
||||||
extern crate registrar;
|
extern crate registrar;
|
||||||
@ -84,6 +82,7 @@ use node_health::NodeHealth;
|
|||||||
|
|
||||||
pub use registrar::{RegistrarClient, Asynchronous};
|
pub use registrar::{RegistrarClient, Asynchronous};
|
||||||
pub use node_health::SyncStatus;
|
pub use node_health::SyncStatus;
|
||||||
|
pub use page::builtin::Dapp;
|
||||||
|
|
||||||
/// Validates Web Proxy tokens
|
/// Validates Web Proxy tokens
|
||||||
pub trait WebProxyTokens: Send + Sync {
|
pub trait WebProxyTokens: Send + Sync {
|
||||||
@ -101,7 +100,6 @@ pub struct Endpoints {
|
|||||||
local_endpoints: Arc<RwLock<Vec<String>>>,
|
local_endpoints: Arc<RwLock<Vec<String>>>,
|
||||||
endpoints: Arc<RwLock<endpoint::Endpoints>>,
|
endpoints: Arc<RwLock<endpoint::Endpoints>>,
|
||||||
dapps_path: PathBuf,
|
dapps_path: PathBuf,
|
||||||
embeddable: Option<ParentFrameSettings>,
|
|
||||||
pool: Option<CpuPool>,
|
pool: Option<CpuPool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +117,7 @@ impl Endpoints {
|
|||||||
None => return,
|
None => return,
|
||||||
Some(pool) => pool,
|
Some(pool) => pool,
|
||||||
};
|
};
|
||||||
let new_local = apps::fs::local_endpoints(&self.dapps_path, self.embeddable.clone(), pool.clone());
|
let new_local = apps::fs::local_endpoints(&self.dapps_path, pool.clone());
|
||||||
let old_local = mem::replace(&mut *self.local_endpoints.write(), new_local.keys().cloned().collect());
|
let old_local = mem::replace(&mut *self.local_endpoints.write(), new_local.keys().cloned().collect());
|
||||||
let (_, to_remove): (_, Vec<_>) = old_local
|
let (_, to_remove): (_, Vec<_>) = old_local
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -151,69 +149,10 @@ impl Middleware {
|
|||||||
&self.endpoints
|
&self.endpoints
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates new middleware for UI server.
|
|
||||||
pub fn ui<F: Fetch>(
|
|
||||||
pool: CpuPool,
|
|
||||||
health: NodeHealth,
|
|
||||||
dapps_domain: &str,
|
|
||||||
registrar: Arc<RegistrarClient<Call=Asynchronous>>,
|
|
||||||
sync_status: Arc<SyncStatus>,
|
|
||||||
fetch: F,
|
|
||||||
info_page_only: bool,
|
|
||||||
) -> Self {
|
|
||||||
let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(
|
|
||||||
hash_fetch::urlhint::URLHintContract::new(registrar),
|
|
||||||
sync_status.clone(),
|
|
||||||
fetch.clone(),
|
|
||||||
pool.clone(),
|
|
||||||
).embeddable_on(None).allow_dapps(false));
|
|
||||||
|
|
||||||
if info_page_only {
|
|
||||||
let mut special = HashMap::default();
|
|
||||||
special.insert(router::SpecialEndpoint::Home, Some(apps::ui_deprecation(pool.clone())));
|
|
||||||
|
|
||||||
return Middleware {
|
|
||||||
endpoints: Default::default(),
|
|
||||||
router: router::Router::new(
|
|
||||||
content_fetcher,
|
|
||||||
None,
|
|
||||||
special,
|
|
||||||
None,
|
|
||||||
dapps_domain.to_owned(),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let special = {
|
|
||||||
let mut special = special_endpoints(
|
|
||||||
pool.clone(),
|
|
||||||
health,
|
|
||||||
content_fetcher.clone(),
|
|
||||||
);
|
|
||||||
special.insert(router::SpecialEndpoint::Home, Some(apps::ui(pool.clone())));
|
|
||||||
special
|
|
||||||
};
|
|
||||||
let router = router::Router::new(
|
|
||||||
content_fetcher,
|
|
||||||
None,
|
|
||||||
special,
|
|
||||||
None,
|
|
||||||
dapps_domain.to_owned(),
|
|
||||||
);
|
|
||||||
|
|
||||||
Middleware {
|
|
||||||
endpoints: Default::default(),
|
|
||||||
router: router,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates new Dapps server middleware.
|
/// Creates new Dapps server middleware.
|
||||||
pub fn dapps<F: Fetch>(
|
pub fn dapps<F: Fetch>(
|
||||||
pool: CpuPool,
|
pool: CpuPool,
|
||||||
health: NodeHealth,
|
health: NodeHealth,
|
||||||
ui_address: Option<(String, u16)>,
|
|
||||||
extra_embed_on: Vec<(String, u16)>,
|
|
||||||
extra_script_src: Vec<(String, u16)>,
|
|
||||||
dapps_path: PathBuf,
|
dapps_path: PathBuf,
|
||||||
extra_dapps: Vec<PathBuf>,
|
extra_dapps: Vec<PathBuf>,
|
||||||
dapps_domain: &str,
|
dapps_domain: &str,
|
||||||
@ -222,18 +161,16 @@ impl Middleware {
|
|||||||
web_proxy_tokens: Arc<WebProxyTokens>,
|
web_proxy_tokens: Arc<WebProxyTokens>,
|
||||||
fetch: F,
|
fetch: F,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let embeddable = as_embeddable(ui_address, extra_embed_on, extra_script_src, dapps_domain);
|
|
||||||
let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(
|
let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(
|
||||||
hash_fetch::urlhint::URLHintContract::new(registrar),
|
hash_fetch::urlhint::URLHintContract::new(registrar),
|
||||||
sync_status.clone(),
|
sync_status.clone(),
|
||||||
fetch.clone(),
|
fetch.clone(),
|
||||||
pool.clone(),
|
pool.clone(),
|
||||||
).embeddable_on(embeddable.clone()).allow_dapps(true));
|
).allow_dapps(true));
|
||||||
let (local_endpoints, endpoints) = apps::all_endpoints(
|
let (local_endpoints, endpoints) = apps::all_endpoints(
|
||||||
dapps_path.clone(),
|
dapps_path.clone(),
|
||||||
extra_dapps,
|
extra_dapps,
|
||||||
dapps_domain,
|
dapps_domain,
|
||||||
embeddable.clone(),
|
|
||||||
web_proxy_tokens,
|
web_proxy_tokens,
|
||||||
fetch.clone(),
|
fetch.clone(),
|
||||||
pool.clone(),
|
pool.clone(),
|
||||||
@ -242,28 +179,18 @@ impl Middleware {
|
|||||||
endpoints: Arc::new(RwLock::new(endpoints)),
|
endpoints: Arc::new(RwLock::new(endpoints)),
|
||||||
dapps_path,
|
dapps_path,
|
||||||
local_endpoints: Arc::new(RwLock::new(local_endpoints)),
|
local_endpoints: Arc::new(RwLock::new(local_endpoints)),
|
||||||
embeddable: embeddable.clone(),
|
|
||||||
pool: Some(pool.clone()),
|
pool: Some(pool.clone()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let special = {
|
let special = special_endpoints(
|
||||||
let mut special = special_endpoints(
|
|
||||||
pool.clone(),
|
|
||||||
health,
|
health,
|
||||||
content_fetcher.clone(),
|
content_fetcher.clone(),
|
||||||
);
|
);
|
||||||
special.insert(
|
|
||||||
router::SpecialEndpoint::Home,
|
|
||||||
Some(apps::ui_redirection(embeddable.clone())),
|
|
||||||
);
|
|
||||||
special
|
|
||||||
};
|
|
||||||
|
|
||||||
let router = router::Router::new(
|
let router = router::Router::new(
|
||||||
content_fetcher,
|
content_fetcher,
|
||||||
Some(endpoints.clone()),
|
Some(endpoints.clone()),
|
||||||
special,
|
special,
|
||||||
embeddable,
|
|
||||||
dapps_domain.to_owned(),
|
dapps_domain.to_owned(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -281,13 +208,11 @@ impl http::RequestMiddleware for Middleware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn special_endpoints(
|
fn special_endpoints(
|
||||||
pool: CpuPool,
|
|
||||||
health: NodeHealth,
|
health: NodeHealth,
|
||||||
content_fetcher: Arc<apps::fetcher::Fetcher>,
|
content_fetcher: Arc<apps::fetcher::Fetcher>,
|
||||||
) -> HashMap<router::SpecialEndpoint, Option<Box<endpoint::Endpoint>>> {
|
) -> HashMap<router::SpecialEndpoint, Option<Box<endpoint::Endpoint>>> {
|
||||||
let mut special = HashMap::new();
|
let mut special = HashMap::new();
|
||||||
special.insert(router::SpecialEndpoint::Rpc, None);
|
special.insert(router::SpecialEndpoint::Rpc, None);
|
||||||
special.insert(router::SpecialEndpoint::Utils, Some(apps::utils(pool)));
|
|
||||||
special.insert(router::SpecialEndpoint::Api, Some(api::RestApi::new(
|
special.insert(router::SpecialEndpoint::Api, Some(api::RestApi::new(
|
||||||
content_fetcher,
|
content_fetcher,
|
||||||
health,
|
health,
|
||||||
@ -295,45 +220,9 @@ fn special_endpoints(
|
|||||||
special
|
special
|
||||||
}
|
}
|
||||||
|
|
||||||
fn address(host: &str, port: u16) -> String {
|
|
||||||
format!("{}:{}", host, port)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_embeddable(
|
|
||||||
ui_address: Option<(String, u16)>,
|
|
||||||
extra_embed_on: Vec<(String, u16)>,
|
|
||||||
extra_script_src: Vec<(String, u16)>,
|
|
||||||
dapps_domain: &str,
|
|
||||||
) -> Option<ParentFrameSettings> {
|
|
||||||
ui_address.map(|(host, port)| ParentFrameSettings {
|
|
||||||
host,
|
|
||||||
port,
|
|
||||||
extra_embed_on,
|
|
||||||
extra_script_src,
|
|
||||||
dapps_domain: dapps_domain.to_owned(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Random filename
|
/// Random filename
|
||||||
fn random_filename() -> String {
|
fn random_filename() -> String {
|
||||||
use ::rand::Rng;
|
use ::rand::Rng;
|
||||||
let mut rng = ::rand::OsRng::new().unwrap();
|
let mut rng = ::rand::OsRng::new().unwrap();
|
||||||
rng.gen_ascii_chars().take(12).collect()
|
rng.gen_ascii_chars().take(12).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
type Embeddable = Option<ParentFrameSettings>;
|
|
||||||
|
|
||||||
/// Parent frame host and port allowed to embed the content.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct ParentFrameSettings {
|
|
||||||
/// Hostname
|
|
||||||
pub host: String,
|
|
||||||
/// Port
|
|
||||||
pub port: u16,
|
|
||||||
/// Additional URLs the dapps can be embedded on.
|
|
||||||
pub extra_embed_on: Vec<(String, u16)>,
|
|
||||||
/// Additional URLs the dapp scripts can be loaded from.
|
|
||||||
pub extra_script_src: Vec<(String, u16)>,
|
|
||||||
/// Dapps Domain (web3.site)
|
|
||||||
pub dapps_domain: String,
|
|
||||||
}
|
|
||||||
|
@ -23,15 +23,13 @@ use parity_dapps::{WebApp, Info};
|
|||||||
|
|
||||||
use endpoint::{Endpoint, EndpointInfo, EndpointPath, Request, Response};
|
use endpoint::{Endpoint, EndpointInfo, EndpointPath, Request, Response};
|
||||||
use page::{handler, PageCache};
|
use page::{handler, PageCache};
|
||||||
use Embeddable;
|
|
||||||
|
|
||||||
|
/// Represents a builtin Dapp.
|
||||||
pub struct Dapp<T: WebApp + 'static> {
|
pub struct Dapp<T: WebApp + 'static> {
|
||||||
/// futures cpu pool
|
/// futures cpu pool
|
||||||
pool: CpuPool,
|
pool: CpuPool,
|
||||||
/// Content of the files
|
/// Content of the files
|
||||||
app: T,
|
app: T,
|
||||||
/// Safe to be loaded in frame by other origin. (use wisely!)
|
|
||||||
safe_to_embed_on: Embeddable,
|
|
||||||
info: EndpointInfo,
|
info: EndpointInfo,
|
||||||
fallback_to_index_html: bool,
|
fallback_to_index_html: bool,
|
||||||
}
|
}
|
||||||
@ -43,7 +41,6 @@ impl<T: WebApp + 'static> Dapp<T> {
|
|||||||
Dapp {
|
Dapp {
|
||||||
pool,
|
pool,
|
||||||
app,
|
app,
|
||||||
safe_to_embed_on: None,
|
|
||||||
info: EndpointInfo::from(info),
|
info: EndpointInfo::from(info),
|
||||||
fallback_to_index_html: false,
|
fallback_to_index_html: false,
|
||||||
}
|
}
|
||||||
@ -56,26 +53,11 @@ impl<T: WebApp + 'static> Dapp<T> {
|
|||||||
Dapp {
|
Dapp {
|
||||||
pool,
|
pool,
|
||||||
app,
|
app,
|
||||||
safe_to_embed_on: None,
|
|
||||||
info: EndpointInfo::from(info),
|
info: EndpointInfo::from(info),
|
||||||
fallback_to_index_html: true,
|
fallback_to_index_html: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates new `Dapp` which can be safely used in iframe
|
|
||||||
/// even from different origin. It might be dangerous (clickjacking).
|
|
||||||
/// Use wisely!
|
|
||||||
pub fn new_safe_to_embed(pool: CpuPool, app: T, address: Embeddable) -> Self {
|
|
||||||
let info = app.info();
|
|
||||||
Dapp {
|
|
||||||
pool,
|
|
||||||
app,
|
|
||||||
safe_to_embed_on: address,
|
|
||||||
info: EndpointInfo::from(info),
|
|
||||||
fallback_to_index_html: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Allow the dapp to use `unsafe-eval` to run JS.
|
/// Allow the dapp to use `unsafe-eval` to run JS.
|
||||||
pub fn allow_js_eval(&mut self) {
|
pub fn allow_js_eval(&mut self) {
|
||||||
self.info.allow_js_eval = Some(true);
|
self.info.allow_js_eval = Some(true);
|
||||||
@ -121,7 +103,6 @@ impl<T: WebApp> Endpoint for Dapp<T> {
|
|||||||
let (reader, response) = handler::PageHandler {
|
let (reader, response) = handler::PageHandler {
|
||||||
file,
|
file,
|
||||||
cache: PageCache::Disabled,
|
cache: PageCache::Disabled,
|
||||||
safe_to_embed_on: self.safe_to_embed_on.clone(),
|
|
||||||
allow_js_eval: self.info.allow_js_eval.clone().unwrap_or(false),
|
allow_js_eval: self.info.allow_js_eval.clone().unwrap_or(false),
|
||||||
}.into_response();
|
}.into_response();
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ use hyper::{self, header, StatusCode};
|
|||||||
use hyper::mime::{Mime};
|
use hyper::mime::{Mime};
|
||||||
|
|
||||||
use handlers::{Reader, ContentHandler, add_security_headers};
|
use handlers::{Reader, ContentHandler, add_security_headers};
|
||||||
use {Embeddable};
|
|
||||||
|
|
||||||
/// Represents a file that can be sent to client.
|
/// Represents a file that can be sent to client.
|
||||||
/// Implementation should keep track of bytes already sent internally.
|
/// Implementation should keep track of bytes already sent internally.
|
||||||
@ -54,8 +53,6 @@ impl Default for PageCache {
|
|||||||
pub struct PageHandler<T: DappFile> {
|
pub struct PageHandler<T: DappFile> {
|
||||||
/// File currently being served
|
/// File currently being served
|
||||||
pub file: Option<T>,
|
pub file: Option<T>,
|
||||||
/// Flag indicating if the file can be safely embeded (put in iframe).
|
|
||||||
pub safe_to_embed_on: Embeddable,
|
|
||||||
/// Cache settings for this page.
|
/// Cache settings for this page.
|
||||||
pub cache: PageCache,
|
pub cache: PageCache,
|
||||||
/// Allow JS unsafe-eval.
|
/// Allow JS unsafe-eval.
|
||||||
@ -70,7 +67,6 @@ impl<T: DappFile> PageHandler<T> {
|
|||||||
"File not found",
|
"File not found",
|
||||||
"Requested file has not been found.",
|
"Requested file has not been found.",
|
||||||
None,
|
None,
|
||||||
self.safe_to_embed_on,
|
|
||||||
).into()),
|
).into()),
|
||||||
Some(file) => file,
|
Some(file) => file,
|
||||||
};
|
};
|
||||||
@ -94,7 +90,7 @@ impl<T: DappFile> PageHandler<T> {
|
|||||||
|
|
||||||
headers.set(header::ContentType(file.content_type().to_owned()));
|
headers.set(header::ContentType(file.content_type().to_owned()));
|
||||||
|
|
||||||
add_security_headers(&mut headers, self.safe_to_embed_on, self.allow_js_eval);
|
add_security_headers(&mut headers, self.allow_js_eval);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (reader, body) = Reader::pair(file.into_reader(), Vec::new());
|
let (reader, body) = Reader::pair(file.into_reader(), Vec::new());
|
||||||
|
@ -22,7 +22,6 @@ use futures_cpupool::CpuPool;
|
|||||||
use page::handler::{self, PageCache};
|
use page::handler::{self, PageCache};
|
||||||
use endpoint::{Endpoint, EndpointInfo, EndpointPath, Request, Response};
|
use endpoint::{Endpoint, EndpointInfo, EndpointPath, Request, Response};
|
||||||
use hyper::mime::Mime;
|
use hyper::mime::Mime;
|
||||||
use Embeddable;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Dapp {
|
pub struct Dapp {
|
||||||
@ -31,7 +30,6 @@ pub struct Dapp {
|
|||||||
mime: Option<Mime>,
|
mime: Option<Mime>,
|
||||||
info: Option<EndpointInfo>,
|
info: Option<EndpointInfo>,
|
||||||
cache: PageCache,
|
cache: PageCache,
|
||||||
embeddable_on: Embeddable,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Dapp {
|
impl fmt::Debug for Dapp {
|
||||||
@ -41,20 +39,18 @@ impl fmt::Debug for Dapp {
|
|||||||
.field("mime", &self.mime)
|
.field("mime", &self.mime)
|
||||||
.field("info", &self.info)
|
.field("info", &self.info)
|
||||||
.field("cache", &self.cache)
|
.field("cache", &self.cache)
|
||||||
.field("embeddable_on", &self.embeddable_on)
|
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dapp {
|
impl Dapp {
|
||||||
pub fn new(pool: CpuPool, path: PathBuf, info: EndpointInfo, cache: PageCache, embeddable_on: Embeddable) -> Self {
|
pub fn new(pool: CpuPool, path: PathBuf, info: EndpointInfo, cache: PageCache) -> Self {
|
||||||
Dapp {
|
Dapp {
|
||||||
pool,
|
pool,
|
||||||
path,
|
path,
|
||||||
mime: None,
|
mime: None,
|
||||||
info: Some(info),
|
info: Some(info),
|
||||||
cache,
|
cache,
|
||||||
embeddable_on,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +61,6 @@ impl Dapp {
|
|||||||
mime: Some(mime),
|
mime: Some(mime),
|
||||||
info: None,
|
info: None,
|
||||||
cache,
|
cache,
|
||||||
embeddable_on: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +91,6 @@ impl Dapp {
|
|||||||
let (reader, response) = handler::PageHandler {
|
let (reader, response) = handler::PageHandler {
|
||||||
file: self.get_file(path),
|
file: self.get_file(path),
|
||||||
cache: self.cache,
|
cache: self.cache,
|
||||||
safe_to_embed_on: self.embeddable_on.clone(),
|
|
||||||
allow_js_eval: self.info.as_ref().and_then(|x| x.allow_js_eval).unwrap_or(false),
|
allow_js_eval: self.info.as_ref().and_then(|x| x.allow_js_eval).unwrap_or(false),
|
||||||
}.into_response();
|
}.into_response();
|
||||||
|
|
||||||
|
@ -21,25 +21,20 @@ use endpoint::{Endpoint, Request, Response, EndpointPath};
|
|||||||
use futures::future;
|
use futures::future;
|
||||||
use handlers::ContentHandler;
|
use handlers::ContentHandler;
|
||||||
use hyper::mime;
|
use hyper::mime;
|
||||||
use {address, Embeddable};
|
|
||||||
|
|
||||||
pub struct ProxyPac {
|
pub struct ProxyPac {
|
||||||
embeddable: Embeddable,
|
|
||||||
dapps_domain: String,
|
dapps_domain: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProxyPac {
|
impl ProxyPac {
|
||||||
pub fn boxed(embeddable: Embeddable, dapps_domain: String) -> Box<Endpoint> {
|
pub fn boxed(dapps_domain: String) -> Box<Endpoint> {
|
||||||
Box::new(ProxyPac { embeddable, dapps_domain })
|
Box::new(ProxyPac { dapps_domain })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Endpoint for ProxyPac {
|
impl Endpoint for ProxyPac {
|
||||||
fn respond(&self, path: EndpointPath, _req: Request) -> Response {
|
fn respond(&self, path: EndpointPath, _req: Request) -> Response {
|
||||||
let ui = self.embeddable
|
let ui = format!("{}:{}", path.host, path.port);
|
||||||
.as_ref()
|
|
||||||
.map(|ref parent| address(&parent.host, parent.port))
|
|
||||||
.unwrap_or_else(|| format!("{}:{}", path.host, path.port));
|
|
||||||
|
|
||||||
let content = format!(
|
let content = format!(
|
||||||
r#"
|
r#"
|
||||||
|
@ -29,14 +29,12 @@ use apps::fetcher::Fetcher;
|
|||||||
use endpoint::{self, Endpoint, EndpointPath};
|
use endpoint::{self, Endpoint, EndpointPath};
|
||||||
use Endpoints;
|
use Endpoints;
|
||||||
use handlers;
|
use handlers;
|
||||||
use Embeddable;
|
|
||||||
|
|
||||||
/// Special endpoints are accessible on every domain (every dapp)
|
/// Special endpoints are accessible on every domain (every dapp)
|
||||||
#[derive(Debug, PartialEq, Hash, Eq)]
|
#[derive(Debug, PartialEq, Hash, Eq)]
|
||||||
pub enum SpecialEndpoint {
|
pub enum SpecialEndpoint {
|
||||||
Rpc,
|
Rpc,
|
||||||
Api,
|
Api,
|
||||||
Utils,
|
|
||||||
Home,
|
Home,
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
@ -52,16 +50,14 @@ pub struct Router {
|
|||||||
endpoints: Option<Endpoints>,
|
endpoints: Option<Endpoints>,
|
||||||
fetch: Arc<Fetcher>,
|
fetch: Arc<Fetcher>,
|
||||||
special: HashMap<SpecialEndpoint, Option<Box<Endpoint>>>,
|
special: HashMap<SpecialEndpoint, Option<Box<Endpoint>>>,
|
||||||
embeddable_on: Embeddable,
|
|
||||||
dapps_domain: String,
|
dapps_domain: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Router {
|
impl Router {
|
||||||
fn resolve_request(&self, req: hyper::Request, refresh_dapps: bool) -> (bool, Response) {
|
fn resolve_request(&self, req: hyper::Request, refresh_dapps: bool) -> Response {
|
||||||
// Choose proper handler depending on path / domain
|
// Choose proper handler depending on path / domain
|
||||||
let endpoint = extract_endpoint(req.uri(), req.headers().get(), &self.dapps_domain);
|
let endpoint = extract_endpoint(req.uri(), req.headers().get(), &self.dapps_domain);
|
||||||
let referer = extract_referer_endpoint(&req, &self.dapps_domain);
|
let referer = extract_referer_endpoint(&req, &self.dapps_domain);
|
||||||
let is_utils = endpoint.1 == SpecialEndpoint::Utils;
|
|
||||||
let is_get_request = *req.method() == hyper::Method::Get;
|
let is_get_request = *req.method() == hyper::Method::Get;
|
||||||
let is_head_request = *req.method() == hyper::Method::Head;
|
let is_head_request = *req.method() == hyper::Method::Head;
|
||||||
let has_dapp = |dapp: &str| self.endpoints
|
let has_dapp = |dapp: &str| self.endpoints
|
||||||
@ -71,7 +67,7 @@ impl Router {
|
|||||||
trace!(target: "dapps", "Routing request to {:?}. Details: {:?}", req.uri(), req);
|
trace!(target: "dapps", "Routing request to {:?}. Details: {:?}", req.uri(), req);
|
||||||
debug!(target: "dapps", "Handling endpoint request: {:?}, referer: {:?}", endpoint, referer);
|
debug!(target: "dapps", "Handling endpoint request: {:?}, referer: {:?}", endpoint, referer);
|
||||||
|
|
||||||
(is_utils, match (endpoint.0, endpoint.1, referer) {
|
match (endpoint.0, endpoint.1, referer) {
|
||||||
// Handle invalid web requests that we can recover from
|
// Handle invalid web requests that we can recover from
|
||||||
(ref path, SpecialEndpoint::None, Some(ref referer))
|
(ref path, SpecialEndpoint::None, Some(ref referer))
|
||||||
if referer.app_id == apps::WEB_PATH
|
if referer.app_id == apps::WEB_PATH
|
||||||
@ -132,7 +128,6 @@ impl Router {
|
|||||||
"404 Not Found",
|
"404 Not Found",
|
||||||
"Requested content was not found.",
|
"Requested content was not found.",
|
||||||
None,
|
None,
|
||||||
self.embeddable_on.clone(),
|
|
||||||
).into())))
|
).into())))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -161,20 +156,19 @@ impl Router {
|
|||||||
"404 Not Found",
|
"404 Not Found",
|
||||||
"Requested content was not found.",
|
"Requested content was not found.",
|
||||||
None,
|
None,
|
||||||
self.embeddable_on.clone(),
|
|
||||||
).into())))
|
).into())))
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl http::RequestMiddleware for Router {
|
impl http::RequestMiddleware for Router {
|
||||||
fn on_request(&self, req: hyper::Request) -> http::RequestMiddlewareAction {
|
fn on_request(&self, req: hyper::Request) -> http::RequestMiddlewareAction {
|
||||||
let is_origin_set = req.headers().get::<header::Origin>().is_some();
|
let is_origin_set = req.headers().get::<header::Origin>().is_some();
|
||||||
let (is_utils, response) = self.resolve_request(req, self.endpoints.is_some());
|
let response = self.resolve_request(req, self.endpoints.is_some());
|
||||||
match response {
|
match response {
|
||||||
Response::Some(response) => http::RequestMiddlewareAction::Respond {
|
Response::Some(response) => http::RequestMiddlewareAction::Respond {
|
||||||
should_validate_hosts: !is_utils,
|
should_validate_hosts: true,
|
||||||
response,
|
response,
|
||||||
},
|
},
|
||||||
Response::None(request) => http::RequestMiddlewareAction::Proceed {
|
Response::None(request) => http::RequestMiddlewareAction::Proceed {
|
||||||
@ -190,14 +184,12 @@ impl Router {
|
|||||||
content_fetcher: Arc<Fetcher>,
|
content_fetcher: Arc<Fetcher>,
|
||||||
endpoints: Option<Endpoints>,
|
endpoints: Option<Endpoints>,
|
||||||
special: HashMap<SpecialEndpoint, Option<Box<Endpoint>>>,
|
special: HashMap<SpecialEndpoint, Option<Box<Endpoint>>>,
|
||||||
embeddable_on: Embeddable,
|
|
||||||
dapps_domain: String,
|
dapps_domain: String,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Router {
|
Router {
|
||||||
endpoints: endpoints,
|
endpoints: endpoints,
|
||||||
fetch: content_fetcher,
|
fetch: content_fetcher,
|
||||||
special: special,
|
special: special,
|
||||||
embeddable_on: embeddable_on,
|
|
||||||
dapps_domain: format!(".{}", dapps_domain),
|
dapps_domain: format!(".{}", dapps_domain),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -250,7 +242,6 @@ fn extract_endpoint(url: &Uri, extra_host: Option<&header::Host>, dapps_domain:
|
|||||||
match path[0].as_ref() {
|
match path[0].as_ref() {
|
||||||
apps::RPC_PATH => SpecialEndpoint::Rpc,
|
apps::RPC_PATH => SpecialEndpoint::Rpc,
|
||||||
apps::API_PATH => SpecialEndpoint::Api,
|
apps::API_PATH => SpecialEndpoint::Api,
|
||||||
apps::UTILS_PATH => SpecialEndpoint::Utils,
|
|
||||||
apps::HOME_PAGE => SpecialEndpoint::Home,
|
apps::HOME_PAGE => SpecialEndpoint::Home,
|
||||||
_ => SpecialEndpoint::None,
|
_ => SpecialEndpoint::None,
|
||||||
}
|
}
|
||||||
@ -351,30 +342,6 @@ mod tests {
|
|||||||
}), SpecialEndpoint::Rpc)
|
}), SpecialEndpoint::Rpc)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
extract_endpoint(&"http://my.status.web3.site/parity-utils/inject.js".parse().unwrap(), None, dapps_domain),
|
|
||||||
(Some(EndpointPath {
|
|
||||||
app_id: "status".to_owned(),
|
|
||||||
app_params: vec!["my".into(), "inject.js".into()],
|
|
||||||
query: None,
|
|
||||||
host: "my.status.web3.site".to_owned(),
|
|
||||||
port: 80,
|
|
||||||
using_dapps_domains: true,
|
|
||||||
}), SpecialEndpoint::Utils)
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
extract_endpoint(&"http://my.status.web3.site/inject.js".parse().unwrap(), None, dapps_domain),
|
|
||||||
(Some(EndpointPath {
|
|
||||||
app_id: "status".to_owned(),
|
|
||||||
app_params: vec!["my".into(), "inject.js".into()],
|
|
||||||
query: None,
|
|
||||||
host: "my.status.web3.site".to_owned(),
|
|
||||||
port: 80,
|
|
||||||
using_dapps_domains: true,
|
|
||||||
}), SpecialEndpoint::None)
|
|
||||||
);
|
|
||||||
|
|
||||||
// By Subdomain
|
// By Subdomain
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
extract_endpoint(&"http://status.web3.site/test.html".parse().unwrap(), None, dapps_domain),
|
extract_endpoint(&"http://status.web3.site/test.html".parse().unwrap(), None, dapps_domain),
|
||||||
|
@ -19,7 +19,7 @@ use rustc_hex::FromHex;
|
|||||||
use tests::helpers::{
|
use tests::helpers::{
|
||||||
serve_with_registrar, serve_with_registrar_and_sync, serve_with_fetch,
|
serve_with_registrar, serve_with_registrar_and_sync, serve_with_fetch,
|
||||||
serve_with_registrar_and_fetch,
|
serve_with_registrar_and_fetch,
|
||||||
request, assert_security_headers_for_embed,
|
request, assert_security_headers
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -40,7 +40,7 @@ fn should_resolve_dapp() {
|
|||||||
// then
|
// then
|
||||||
response.assert_status("HTTP/1.1 404 Not Found");
|
response.assert_status("HTTP/1.1 404 Not Found");
|
||||||
assert_eq!(registrar.calls.lock().len(), 4);
|
assert_eq!(registrar.calls.lock().len(), 4);
|
||||||
assert_security_headers_for_embed(&response.headers);
|
assert_security_headers(&response.headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -61,7 +61,7 @@ fn should_return_503_when_syncing_but_should_make_the_calls() {
|
|||||||
// then
|
// then
|
||||||
response.assert_status("HTTP/1.1 503 Service Unavailable");
|
response.assert_status("HTTP/1.1 503 Service Unavailable");
|
||||||
assert_eq!(registrar.calls.lock().len(), 2);
|
assert_eq!(registrar.calls.lock().len(), 2);
|
||||||
assert_security_headers_for_embed(&response.headers);
|
assert_security_headers(&response.headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
const GAVCOIN_DAPP: &'static str = "00000000000000000000000000000000000000000000000000000000000000609faf32e1e3845e237cc6efd27187cee13b3b99db000000000000000000000000000000000000000000000000d8bd350823e28ff75e74a34215faefdc8a52fd8e00000000000000000000000000000000000000000000000000000000000000116761766f66796f726b2f676176636f696e000000000000000000000000000000";
|
const GAVCOIN_DAPP: &'static str = "00000000000000000000000000000000000000000000000000000000000000609faf32e1e3845e237cc6efd27187cee13b3b99db000000000000000000000000000000000000000000000000d8bd350823e28ff75e74a34215faefdc8a52fd8e00000000000000000000000000000000000000000000000000000000000000116761766f66796f726b2f676176636f696e000000000000000000000000000000";
|
||||||
@ -95,7 +95,7 @@ fn should_return_502_on_hash_mismatch() {
|
|||||||
|
|
||||||
response.assert_status("HTTP/1.1 502 Bad Gateway");
|
response.assert_status("HTTP/1.1 502 Bad Gateway");
|
||||||
assert!(response.body.contains("HashMismatch"), "Expected hash mismatch response, got: {:?}", response.body);
|
assert!(response.body.contains("HashMismatch"), "Expected hash mismatch response, got: {:?}", response.body);
|
||||||
assert_security_headers_for_embed(&response.headers);
|
assert_security_headers(&response.headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -126,7 +126,7 @@ fn should_return_error_for_invalid_dapp_zip() {
|
|||||||
|
|
||||||
response.assert_status("HTTP/1.1 502 Bad Gateway");
|
response.assert_status("HTTP/1.1 502 Bad Gateway");
|
||||||
assert!(response.body.contains("InvalidArchive"), "Expected invalid zip response, got: {:?}", response.body);
|
assert!(response.body.contains("InvalidArchive"), "Expected invalid zip response, got: {:?}", response.body);
|
||||||
assert_security_headers_for_embed(&response.headers);
|
assert_security_headers(&response.headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -165,7 +165,7 @@ fn should_return_fetched_dapp_content() {
|
|||||||
fetch.assert_no_more_requests();
|
fetch.assert_no_more_requests();
|
||||||
|
|
||||||
response1.assert_status("HTTP/1.1 200 OK");
|
response1.assert_status("HTTP/1.1 200 OK");
|
||||||
assert_security_headers_for_embed(&response1.headers);
|
assert_security_headers(&response1.headers);
|
||||||
assert!(
|
assert!(
|
||||||
response1.body.contains(r#"18
|
response1.body.contains(r#"18
|
||||||
<h1>Hello Gavcoin!</h1>
|
<h1>Hello Gavcoin!</h1>
|
||||||
@ -178,7 +178,7 @@ fn should_return_fetched_dapp_content() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
response2.assert_status("HTTP/1.1 200 OK");
|
response2.assert_status("HTTP/1.1 200 OK");
|
||||||
assert_security_headers_for_embed(&response2.headers);
|
assert_security_headers(&response2.headers);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
response2.body,
|
response2.body,
|
||||||
r#"EA
|
r#"EA
|
||||||
@ -331,7 +331,7 @@ fn should_stream_web_content() {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
response.assert_status("HTTP/1.1 200 OK");
|
response.assert_status("HTTP/1.1 200 OK");
|
||||||
assert_security_headers_for_embed(&response.headers);
|
assert_security_headers(&response.headers);
|
||||||
|
|
||||||
fetch.assert_requested("https://parity.io/");
|
fetch.assert_requested("https://parity.io/");
|
||||||
fetch.assert_no_more_requests();
|
fetch.assert_no_more_requests();
|
||||||
@ -354,7 +354,7 @@ fn should_support_base32_encoded_web_urls() {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
response.assert_status("HTTP/1.1 200 OK");
|
response.assert_status("HTTP/1.1 200 OK");
|
||||||
assert_security_headers_for_embed(&response.headers);
|
assert_security_headers(&response.headers);
|
||||||
|
|
||||||
fetch.assert_requested("https://parity.io/styles.css?test=123");
|
fetch.assert_requested("https://parity.io/styles.css?test=123");
|
||||||
fetch.assert_no_more_requests();
|
fetch.assert_no_more_requests();
|
||||||
@ -377,7 +377,7 @@ fn should_correctly_handle_long_label_when_splitted() {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
response.assert_status("HTTP/1.1 200 OK");
|
response.assert_status("HTTP/1.1 200 OK");
|
||||||
assert_security_headers_for_embed(&response.headers);
|
assert_security_headers(&response.headers);
|
||||||
|
|
||||||
fetch.assert_requested("https://contribution.melonport.com/styles.css?test=123");
|
fetch.assert_requested("https://contribution.melonport.com/styles.css?test=123");
|
||||||
fetch.assert_no_more_requests();
|
fetch.assert_no_more_requests();
|
||||||
@ -400,7 +400,7 @@ fn should_support_base32_encoded_web_urls_as_path() {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
response.assert_status("HTTP/1.1 200 OK");
|
response.assert_status("HTTP/1.1 200 OK");
|
||||||
assert_security_headers_for_embed(&response.headers);
|
assert_security_headers(&response.headers);
|
||||||
|
|
||||||
fetch.assert_requested("https://parity.io/styles.css?test=123");
|
fetch.assert_requested("https://parity.io/styles.css?test=123");
|
||||||
fetch.assert_no_more_requests();
|
fetch.assert_no_more_requests();
|
||||||
@ -423,7 +423,7 @@ fn should_return_error_on_non_whitelisted_domain() {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
response.assert_status("HTTP/1.1 400 Bad Request");
|
response.assert_status("HTTP/1.1 400 Bad Request");
|
||||||
assert_security_headers_for_embed(&response.headers);
|
assert_security_headers(&response.headers);
|
||||||
|
|
||||||
fetch.assert_no_more_requests();
|
fetch.assert_no_more_requests();
|
||||||
}
|
}
|
||||||
@ -445,7 +445,7 @@ fn should_return_error_on_invalid_token() {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
response.assert_status("HTTP/1.1 400 Bad Request");
|
response.assert_status("HTTP/1.1 400 Bad Request");
|
||||||
assert_security_headers_for_embed(&response.headers);
|
assert_security_headers(&response.headers);
|
||||||
|
|
||||||
fetch.assert_no_more_requests();
|
fetch.assert_no_more_requests();
|
||||||
}
|
}
|
||||||
@ -467,7 +467,7 @@ fn should_return_error_on_invalid_protocol() {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
response.assert_status("HTTP/1.1 400 Bad Request");
|
response.assert_status("HTTP/1.1 400 Bad Request");
|
||||||
assert_security_headers_for_embed(&response.headers);
|
assert_security_headers(&response.headers);
|
||||||
|
|
||||||
fetch.assert_no_more_requests();
|
fetch.assert_no_more_requests();
|
||||||
}
|
}
|
||||||
@ -492,7 +492,7 @@ fn should_disallow_non_get_requests() {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
response.assert_status("HTTP/1.1 405 Method Not Allowed");
|
response.assert_status("HTTP/1.1 405 Method Not Allowed");
|
||||||
assert_security_headers_for_embed(&response.headers);
|
assert_security_headers(&response.headers);
|
||||||
|
|
||||||
fetch.assert_no_more_requests();
|
fetch.assert_no_more_requests();
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,6 @@ mod fetch;
|
|||||||
use self::registrar::FakeRegistrar;
|
use self::registrar::FakeRegistrar;
|
||||||
use self::fetch::FakeFetch;
|
use self::fetch::FakeFetch;
|
||||||
|
|
||||||
const SIGNER_PORT: u16 = 18180;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct FakeSync(bool);
|
struct FakeSync(bool);
|
||||||
impl SyncStatus for FakeSync {
|
impl SyncStatus for FakeSync {
|
||||||
@ -63,8 +61,7 @@ pub fn init_server<F, B>(process: F, io: IoHandler) -> (Server, Arc<FakeRegistra
|
|||||||
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(FetchClient::new().unwrap(), &dapps_path, registrar.clone());
|
let builder = ServerBuilder::new(FetchClient::new().unwrap(), &dapps_path, registrar.clone());
|
||||||
builder.signer_address = Some(("127.0.0.1".into(), SIGNER_PORT));
|
|
||||||
let server = process(builder).start_unsecured_http(&"127.0.0.1:0".parse().unwrap(), io).unwrap();
|
let server = process(builder).start_unsecured_http(&"127.0.0.1:0".parse().unwrap(), io).unwrap();
|
||||||
(
|
(
|
||||||
server,
|
server,
|
||||||
@ -122,13 +119,6 @@ pub fn serve() -> Server {
|
|||||||
init_server(|builder| builder, Default::default()).0
|
init_server(|builder| builder, Default::default()).0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serve_ui() -> Server {
|
|
||||||
init_server(|mut builder| {
|
|
||||||
builder.serve_ui = true;
|
|
||||||
builder
|
|
||||||
}, Default::default()).0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn request(server: Server, request: &str) -> http_client::Response {
|
pub fn request(server: Server, request: &str) -> http_client::Response {
|
||||||
http_client::request(server.addr(), request)
|
http_client::request(server.addr(), request)
|
||||||
}
|
}
|
||||||
@ -136,9 +126,6 @@ pub fn request(server: Server, request: &str) -> http_client::Response {
|
|||||||
pub fn assert_security_headers(headers: &[String]) {
|
pub fn assert_security_headers(headers: &[String]) {
|
||||||
http_client::assert_security_headers_present(headers, None)
|
http_client::assert_security_headers_present(headers, None)
|
||||||
}
|
}
|
||||||
pub fn assert_security_headers_for_embed(headers: &[String]) {
|
|
||||||
http_client::assert_security_headers_present(headers, Some(SIGNER_PORT))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Webapps HTTP+RPC server build.
|
/// Webapps HTTP+RPC server build.
|
||||||
pub struct ServerBuilder<T: Fetch = FetchClient> {
|
pub struct ServerBuilder<T: Fetch = FetchClient> {
|
||||||
@ -146,10 +133,8 @@ pub struct ServerBuilder<T: Fetch = FetchClient> {
|
|||||||
registrar: Arc<RegistrarClient<Call=Asynchronous>>,
|
registrar: Arc<RegistrarClient<Call=Asynchronous>>,
|
||||||
sync_status: Arc<SyncStatus>,
|
sync_status: Arc<SyncStatus>,
|
||||||
web_proxy_tokens: Arc<WebProxyTokens>,
|
web_proxy_tokens: Arc<WebProxyTokens>,
|
||||||
signer_address: Option<(String, u16)>,
|
|
||||||
allowed_hosts: DomainsValidation<Host>,
|
allowed_hosts: DomainsValidation<Host>,
|
||||||
fetch: T,
|
fetch: T,
|
||||||
serve_ui: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerBuilder {
|
impl ServerBuilder {
|
||||||
@ -160,10 +145,8 @@ impl ServerBuilder {
|
|||||||
registrar: registrar,
|
registrar: registrar,
|
||||||
sync_status: Arc::new(FakeSync(false)),
|
sync_status: Arc::new(FakeSync(false)),
|
||||||
web_proxy_tokens: Arc::new(|_| None),
|
web_proxy_tokens: Arc::new(|_| None),
|
||||||
signer_address: None,
|
|
||||||
allowed_hosts: DomainsValidation::Disabled,
|
allowed_hosts: DomainsValidation::Disabled,
|
||||||
fetch: fetch,
|
fetch: fetch,
|
||||||
serve_ui: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -176,10 +159,8 @@ impl<T: Fetch> ServerBuilder<T> {
|
|||||||
registrar: self.registrar,
|
registrar: self.registrar,
|
||||||
sync_status: self.sync_status,
|
sync_status: self.sync_status,
|
||||||
web_proxy_tokens: self.web_proxy_tokens,
|
web_proxy_tokens: self.web_proxy_tokens,
|
||||||
signer_address: self.signer_address,
|
|
||||||
allowed_hosts: self.allowed_hosts,
|
allowed_hosts: self.allowed_hosts,
|
||||||
fetch: fetch,
|
fetch: fetch,
|
||||||
serve_ui: self.serve_ui,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +171,6 @@ impl<T: Fetch> ServerBuilder<T> {
|
|||||||
addr,
|
addr,
|
||||||
io,
|
io,
|
||||||
self.allowed_hosts,
|
self.allowed_hosts,
|
||||||
self.signer_address,
|
|
||||||
self.dapps_path,
|
self.dapps_path,
|
||||||
vec![],
|
vec![],
|
||||||
self.registrar,
|
self.registrar,
|
||||||
@ -198,7 +178,6 @@ impl<T: Fetch> ServerBuilder<T> {
|
|||||||
self.web_proxy_tokens,
|
self.web_proxy_tokens,
|
||||||
Remote::new_sync(),
|
Remote::new_sync(),
|
||||||
self.fetch,
|
self.fetch,
|
||||||
self.serve_ui,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -215,7 +194,6 @@ impl Server {
|
|||||||
addr: &SocketAddr,
|
addr: &SocketAddr,
|
||||||
io: IoHandler,
|
io: IoHandler,
|
||||||
allowed_hosts: DomainsValidation<Host>,
|
allowed_hosts: DomainsValidation<Host>,
|
||||||
signer_address: Option<(String, u16)>,
|
|
||||||
dapps_path: PathBuf,
|
dapps_path: PathBuf,
|
||||||
extra_dapps: Vec<PathBuf>,
|
extra_dapps: Vec<PathBuf>,
|
||||||
registrar: Arc<RegistrarClient<Call=Asynchronous>>,
|
registrar: Arc<RegistrarClient<Call=Asynchronous>>,
|
||||||
@ -223,7 +201,6 @@ impl Server {
|
|||||||
web_proxy_tokens: Arc<WebProxyTokens>,
|
web_proxy_tokens: Arc<WebProxyTokens>,
|
||||||
remote: Remote,
|
remote: Remote,
|
||||||
fetch: F,
|
fetch: F,
|
||||||
serve_ui: bool,
|
|
||||||
) -> io::Result<Server> {
|
) -> io::Result<Server> {
|
||||||
let health = NodeHealth::new(
|
let health = NodeHealth::new(
|
||||||
sync_status.clone(),
|
sync_status.clone(),
|
||||||
@ -231,23 +208,10 @@ impl Server {
|
|||||||
remote.clone(),
|
remote.clone(),
|
||||||
);
|
);
|
||||||
let pool = ::futures_cpupool::CpuPool::new(1);
|
let pool = ::futures_cpupool::CpuPool::new(1);
|
||||||
let middleware = if serve_ui {
|
let middleware =
|
||||||
Middleware::ui(
|
|
||||||
pool,
|
|
||||||
health,
|
|
||||||
DAPPS_DOMAIN.into(),
|
|
||||||
registrar,
|
|
||||||
sync_status,
|
|
||||||
fetch,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Middleware::dapps(
|
Middleware::dapps(
|
||||||
pool,
|
pool,
|
||||||
health,
|
health,
|
||||||
signer_address,
|
|
||||||
vec![],
|
|
||||||
vec![],
|
|
||||||
dapps_path,
|
dapps_path,
|
||||||
extra_dapps,
|
extra_dapps,
|
||||||
DAPPS_DOMAIN.into(),
|
DAPPS_DOMAIN.into(),
|
||||||
@ -255,8 +219,7 @@ impl Server {
|
|||||||
sync_status,
|
sync_status,
|
||||||
web_proxy_tokens,
|
web_proxy_tokens,
|
||||||
fetch,
|
fetch,
|
||||||
)
|
);
|
||||||
};
|
|
||||||
|
|
||||||
let mut allowed_hosts: Option<Vec<Host>> = allowed_hosts.into();
|
let mut allowed_hosts: Option<Vec<Host>> = allowed_hosts.into();
|
||||||
allowed_hosts.as_mut().map(|hosts| {
|
allowed_hosts.as_mut().map(|hosts| {
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is part of Parity.
|
|
||||||
|
|
||||||
// Parity is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// Parity is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
use tests::helpers::{serve_ui, request, assert_security_headers};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_serve_home_js() {
|
|
||||||
// given
|
|
||||||
let server = serve_ui();
|
|
||||||
|
|
||||||
// when
|
|
||||||
let response = request(server,
|
|
||||||
"\
|
|
||||||
GET /inject.js HTTP/1.1\r\n\
|
|
||||||
Host: 127.0.0.1:8080\r\n\
|
|
||||||
Connection: close\r\n\
|
|
||||||
\r\n\
|
|
||||||
{}
|
|
||||||
"
|
|
||||||
);
|
|
||||||
|
|
||||||
// then
|
|
||||||
response.assert_status("HTTP/1.1 200 OK");
|
|
||||||
response.assert_header("Content-Type", "application/javascript");
|
|
||||||
assert_eq!(response.body.contains("function(){"), true, "Expected function in: {}", response.body);
|
|
||||||
assert_security_headers(&response.headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_serve_home() {
|
|
||||||
// given
|
|
||||||
let server = serve_ui();
|
|
||||||
|
|
||||||
// when
|
|
||||||
let response = request(server,
|
|
||||||
"\
|
|
||||||
GET / HTTP/1.1\r\n\
|
|
||||||
Host: 127.0.0.1:8080\r\n\
|
|
||||||
Connection: close\r\n\
|
|
||||||
\r\n\
|
|
||||||
{}
|
|
||||||
"
|
|
||||||
);
|
|
||||||
|
|
||||||
// then
|
|
||||||
response.assert_status("HTTP/1.1 200 OK");
|
|
||||||
response.assert_header("Content-Type", "text/html");
|
|
||||||
assert_security_headers(&response.headers);
|
|
||||||
}
|
|
@ -20,7 +20,5 @@ mod helpers;
|
|||||||
|
|
||||||
mod api;
|
mod api;
|
||||||
mod fetch;
|
mod fetch;
|
||||||
mod home;
|
|
||||||
mod redirection;
|
|
||||||
mod rpc;
|
mod rpc;
|
||||||
mod validation;
|
mod validation;
|
||||||
|
@ -1,206 +0,0 @@
|
|||||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is part of Parity.
|
|
||||||
|
|
||||||
// Parity is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// Parity is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
use tests::helpers::{serve, request, assert_security_headers, assert_security_headers_for_embed};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_redirect_to_home() {
|
|
||||||
// given
|
|
||||||
let server = serve();
|
|
||||||
|
|
||||||
// when
|
|
||||||
let response = request(server,
|
|
||||||
"\
|
|
||||||
GET / HTTP/1.1\r\n\
|
|
||||||
Host: 127.0.0.1:8080\r\n\
|
|
||||||
Connection: close\r\n\
|
|
||||||
\r\n\
|
|
||||||
"
|
|
||||||
);
|
|
||||||
|
|
||||||
// then
|
|
||||||
response.assert_status("HTTP/1.1 302 Found");
|
|
||||||
assert_eq!(response.headers.get(0).unwrap(), "Location: http://127.0.0.1:18180");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_redirect_to_home_with_domain() {
|
|
||||||
// given
|
|
||||||
let server = serve();
|
|
||||||
|
|
||||||
// when
|
|
||||||
let response = request(server,
|
|
||||||
"\
|
|
||||||
GET / HTTP/1.1\r\n\
|
|
||||||
Host: home.web3.site\r\n\
|
|
||||||
Connection: close\r\n\
|
|
||||||
\r\n\
|
|
||||||
"
|
|
||||||
);
|
|
||||||
|
|
||||||
// then
|
|
||||||
response.assert_status("HTTP/1.1 302 Found");
|
|
||||||
assert_eq!(response.headers.get(0).unwrap(), "Location: http://127.0.0.1:18180");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_redirect_to_home_when_trailing_slash_is_missing() {
|
|
||||||
// given
|
|
||||||
let server = serve();
|
|
||||||
|
|
||||||
// when
|
|
||||||
let response = request(server,
|
|
||||||
"\
|
|
||||||
GET /app HTTP/1.1\r\n\
|
|
||||||
Host: 127.0.0.1:8080\r\n\
|
|
||||||
Connection: close\r\n\
|
|
||||||
\r\n\
|
|
||||||
"
|
|
||||||
);
|
|
||||||
|
|
||||||
// then
|
|
||||||
response.assert_status("HTTP/1.1 302 Found");
|
|
||||||
assert_eq!(response.headers.get(0).unwrap(), "Location: http://127.0.0.1:18180");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_display_404_on_invalid_dapp() {
|
|
||||||
// given
|
|
||||||
let server = serve();
|
|
||||||
|
|
||||||
// when
|
|
||||||
let response = request(server,
|
|
||||||
"\
|
|
||||||
GET /invaliddapp/ HTTP/1.1\r\n\
|
|
||||||
Host: 127.0.0.1:8080\r\n\
|
|
||||||
Connection: close\r\n\
|
|
||||||
\r\n\
|
|
||||||
"
|
|
||||||
);
|
|
||||||
|
|
||||||
// then
|
|
||||||
response.assert_status("HTTP/1.1 404 Not Found");
|
|
||||||
assert_security_headers_for_embed(&response.headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_display_404_on_invalid_dapp_with_domain() {
|
|
||||||
// given
|
|
||||||
let server = serve();
|
|
||||||
|
|
||||||
// when
|
|
||||||
let response = request(server,
|
|
||||||
"\
|
|
||||||
GET / HTTP/1.1\r\n\
|
|
||||||
Host: invaliddapp.web3.site\r\n\
|
|
||||||
Connection: close\r\n\
|
|
||||||
\r\n\
|
|
||||||
"
|
|
||||||
);
|
|
||||||
|
|
||||||
// then
|
|
||||||
response.assert_status("HTTP/1.1 404 Not Found");
|
|
||||||
assert_security_headers_for_embed(&response.headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_serve_rpc() {
|
|
||||||
// given
|
|
||||||
let server = serve();
|
|
||||||
|
|
||||||
// when
|
|
||||||
let response = request(server,
|
|
||||||
"\
|
|
||||||
POST / HTTP/1.1\r\n\
|
|
||||||
Host: 127.0.0.1:8080\r\n\
|
|
||||||
Connection: close\r\n\
|
|
||||||
Content-Type: application/json\r\n
|
|
||||||
\r\n\
|
|
||||||
{}
|
|
||||||
"
|
|
||||||
);
|
|
||||||
|
|
||||||
// then
|
|
||||||
response.assert_status("HTTP/1.1 200 OK");
|
|
||||||
assert_eq!(response.body, format!("4C\n{}\n\n0\n\n", r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error"},"id":null}"#));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_serve_rpc_at_slash_rpc() {
|
|
||||||
// given
|
|
||||||
let server = serve();
|
|
||||||
|
|
||||||
// when
|
|
||||||
let response = request(server,
|
|
||||||
"\
|
|
||||||
POST /rpc HTTP/1.1\r\n\
|
|
||||||
Host: 127.0.0.1:8080\r\n\
|
|
||||||
Connection: close\r\n\
|
|
||||||
Content-Type: application/json\r\n
|
|
||||||
\r\n\
|
|
||||||
{}
|
|
||||||
"
|
|
||||||
);
|
|
||||||
|
|
||||||
// then
|
|
||||||
response.assert_status("HTTP/1.1 200 OK");
|
|
||||||
assert_eq!(response.body, format!("4C\n{}\n\n0\n\n", r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error"},"id":null}"#));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_serve_proxy_pac() {
|
|
||||||
// given
|
|
||||||
let server = serve();
|
|
||||||
|
|
||||||
// when
|
|
||||||
let response = request(server,
|
|
||||||
"\
|
|
||||||
GET /proxy/proxy.pac HTTP/1.1\r\n\
|
|
||||||
Host: 127.0.0.1:8080\r\n\
|
|
||||||
Connection: close\r\n\
|
|
||||||
\r\n\
|
|
||||||
{}
|
|
||||||
"
|
|
||||||
);
|
|
||||||
|
|
||||||
// then
|
|
||||||
response.assert_status("HTTP/1.1 200 OK");
|
|
||||||
assert_eq!(response.body, "DB\n\nfunction FindProxyForURL(url, host) {\n\tif (shExpMatch(host, \"home.web3.site\"))\n\t{\n\t\treturn \"PROXY 127.0.0.1:18180\";\n\t}\n\n\tif (shExpMatch(host, \"*.web3.site\"))\n\t{\n\t\treturn \"PROXY 127.0.0.1:8080\";\n\t}\n\n\treturn \"DIRECT\";\n}\n\n0\n\n".to_owned());
|
|
||||||
assert_security_headers(&response.headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_serve_utils() {
|
|
||||||
// given
|
|
||||||
let server = serve();
|
|
||||||
|
|
||||||
// when
|
|
||||||
let response = request(server,
|
|
||||||
"\
|
|
||||||
GET /parity-utils/inject.js HTTP/1.1\r\n\
|
|
||||||
Host: 127.0.0.1:8080\r\n\
|
|
||||||
Connection: close\r\n\
|
|
||||||
\r\n\
|
|
||||||
{}
|
|
||||||
"
|
|
||||||
);
|
|
||||||
|
|
||||||
// then
|
|
||||||
response.assert_status("HTTP/1.1 200 OK");
|
|
||||||
response.assert_header("Content-Type", "application/javascript");
|
|
||||||
assert_eq!(response.body.contains("function(){"), true, "Expected function in: {}", response.body);
|
|
||||||
assert_security_headers(&response.headers);
|
|
||||||
}
|
|
@ -37,26 +37,6 @@ fn should_reject_invalid_host() {
|
|||||||
assert!(response.body.contains("Provided Host header is not whitelisted."), response.body);
|
assert!(response.body.contains("Provided Host header is not whitelisted."), response.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_allow_valid_host() {
|
|
||||||
// given
|
|
||||||
let server = serve_hosts(Some(vec!["localhost:8080".into()]));
|
|
||||||
|
|
||||||
// when
|
|
||||||
let response = request(server,
|
|
||||||
"\
|
|
||||||
GET /ui/ HTTP/1.1\r\n\
|
|
||||||
Host: localhost:8080\r\n\
|
|
||||||
Connection: close\r\n\
|
|
||||||
\r\n\
|
|
||||||
{}
|
|
||||||
"
|
|
||||||
);
|
|
||||||
|
|
||||||
// then
|
|
||||||
response.assert_status("HTTP/1.1 200 OK");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_serve_dapps_domains() {
|
fn should_serve_dapps_domains() {
|
||||||
// given
|
// given
|
||||||
@ -66,28 +46,7 @@ fn should_serve_dapps_domains() {
|
|||||||
let response = request(server,
|
let response = request(server,
|
||||||
"\
|
"\
|
||||||
GET / HTTP/1.1\r\n\
|
GET / HTTP/1.1\r\n\
|
||||||
Host: ui.web3.site\r\n\
|
Host: proxy.web3.site\r\n\
|
||||||
Connection: close\r\n\
|
|
||||||
\r\n\
|
|
||||||
{}
|
|
||||||
"
|
|
||||||
);
|
|
||||||
|
|
||||||
// then
|
|
||||||
response.assert_status("HTTP/1.1 200 OK");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
// NOTE [todr] This is required for error pages to be styled properly.
|
|
||||||
fn should_allow_parity_utils_even_on_invalid_domain() {
|
|
||||||
// given
|
|
||||||
let server = serve_hosts(Some(vec!["localhost:8080".into()]));
|
|
||||||
|
|
||||||
// when
|
|
||||||
let response = request(server,
|
|
||||||
"\
|
|
||||||
GET /parity-utils/styles.css HTTP/1.1\r\n\
|
|
||||||
Host: 127.0.0.1:8080\r\n\
|
|
||||||
Connection: close\r\n\
|
Connection: close\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
{}
|
{}
|
||||||
|
@ -30,10 +30,9 @@ use handlers::{
|
|||||||
ContentFetcherHandler, ContentHandler, ContentValidator, ValidatorResponse,
|
ContentFetcherHandler, ContentHandler, ContentValidator, ValidatorResponse,
|
||||||
StreamingHandler,
|
StreamingHandler,
|
||||||
};
|
};
|
||||||
use {Embeddable, WebProxyTokens};
|
use WebProxyTokens;
|
||||||
|
|
||||||
pub struct Web<F> {
|
pub struct Web<F> {
|
||||||
embeddable_on: Embeddable,
|
|
||||||
web_proxy_tokens: Arc<WebProxyTokens>,
|
web_proxy_tokens: Arc<WebProxyTokens>,
|
||||||
fetch: F,
|
fetch: F,
|
||||||
pool: CpuPool,
|
pool: CpuPool,
|
||||||
@ -41,13 +40,11 @@ pub struct Web<F> {
|
|||||||
|
|
||||||
impl<F: Fetch> Web<F> {
|
impl<F: Fetch> Web<F> {
|
||||||
pub fn boxed(
|
pub fn boxed(
|
||||||
embeddable_on: Embeddable,
|
|
||||||
web_proxy_tokens: Arc<WebProxyTokens>,
|
web_proxy_tokens: Arc<WebProxyTokens>,
|
||||||
fetch: F,
|
fetch: F,
|
||||||
pool: CpuPool,
|
pool: CpuPool,
|
||||||
) -> Box<Endpoint> {
|
) -> Box<Endpoint> {
|
||||||
Box::new(Web {
|
Box::new(Web {
|
||||||
embeddable_on,
|
|
||||||
web_proxy_tokens,
|
web_proxy_tokens,
|
||||||
fetch,
|
fetch,
|
||||||
pool,
|
pool,
|
||||||
@ -64,7 +61,6 @@ impl<F: Fetch> Web<F> {
|
|||||||
"Invalid parameter",
|
"Invalid parameter",
|
||||||
"Couldn't parse given parameter:",
|
"Couldn't parse given parameter:",
|
||||||
path.app_params.get(0).map(String::as_str),
|
path.app_params.get(0).map(String::as_str),
|
||||||
self.embeddable_on.clone()
|
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
let mut token_it = token_and_url.split('+');
|
let mut token_it = token_and_url.split('+');
|
||||||
@ -76,7 +72,7 @@ impl<F: Fetch> Web<F> {
|
|||||||
Some(domain) => domain,
|
Some(domain) => domain,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ContentHandler::error(
|
return Err(ContentHandler::error(
|
||||||
StatusCode::BadRequest, "Invalid Access Token", "Invalid or old web proxy access token supplied.", Some("Try refreshing the page."), self.embeddable_on.clone()
|
StatusCode::BadRequest, "Invalid Access Token", "Invalid or old web proxy access token supplied.", Some("Try refreshing the page."),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -86,14 +82,14 @@ impl<F: Fetch> Web<F> {
|
|||||||
Some(url) if url.starts_with("http://") || url.starts_with("https://") => url.to_owned(),
|
Some(url) if url.starts_with("http://") || url.starts_with("https://") => url.to_owned(),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ContentHandler::error(
|
return Err(ContentHandler::error(
|
||||||
StatusCode::BadRequest, "Invalid Protocol", "Invalid protocol used.", None, self.embeddable_on.clone()
|
StatusCode::BadRequest, "Invalid Protocol", "Invalid protocol used.", None,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if !target_url.starts_with(&*domain) {
|
if !target_url.starts_with(&*domain) {
|
||||||
return Err(ContentHandler::error(
|
return Err(ContentHandler::error(
|
||||||
StatusCode::BadRequest, "Invalid Domain", "Dapp attempted to access invalid domain.", Some(&target_url), self.embeddable_on.clone(),
|
StatusCode::BadRequest, "Invalid Domain", "Dapp attempted to access invalid domain.", Some(&target_url),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,10 +124,8 @@ impl<F: Fetch> Endpoint for Web<F> {
|
|||||||
&target_url,
|
&target_url,
|
||||||
path,
|
path,
|
||||||
WebInstaller {
|
WebInstaller {
|
||||||
embeddable_on: self.embeddable_on.clone(),
|
|
||||||
token,
|
token,
|
||||||
},
|
},
|
||||||
self.embeddable_on.clone(),
|
|
||||||
self.fetch.clone(),
|
self.fetch.clone(),
|
||||||
self.pool.clone(),
|
self.pool.clone(),
|
||||||
))
|
))
|
||||||
@ -139,7 +133,6 @@ impl<F: Fetch> Endpoint for Web<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct WebInstaller {
|
struct WebInstaller {
|
||||||
embeddable_on: Embeddable,
|
|
||||||
token: String,
|
token: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,12 +147,10 @@ impl ContentValidator for WebInstaller {
|
|||||||
fetch::BodyReader::new(response),
|
fetch::BodyReader::new(response),
|
||||||
status,
|
status,
|
||||||
mime,
|
mime,
|
||||||
self.embeddable_on,
|
|
||||||
);
|
);
|
||||||
if is_html {
|
if is_html {
|
||||||
handler.set_initial_content(&format!(
|
handler.set_initial_content(&format!(
|
||||||
r#"<script src="/{}/inject.js"></script><script>history.replaceState({{}}, "", "/?{}{}/{}")</script>"#,
|
r#"<script>history.replaceState({{}}, "", "/?{}{}/{}")</script>"#,
|
||||||
apps::UTILS_PATH,
|
|
||||||
apps::URL_REFERER,
|
apps::URL_REFERER,
|
||||||
apps::WEB_PATH,
|
apps::WEB_PATH,
|
||||||
&self.token,
|
&self.token,
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
[package]
|
|
||||||
description = "Parity UI deprecation notice."
|
|
||||||
name = "parity-ui-deprecation"
|
|
||||||
version = "1.10.0"
|
|
||||||
license = "GPL-3.0"
|
|
||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
|
||||||
build = "build.rs"
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["with-syntex", "use-precompiled-js"]
|
|
||||||
use-precompiled-js = ["parity-dapps-glue/use-precompiled-js"]
|
|
||||||
with-syntex = ["parity-dapps-glue/with-syntex"]
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
parity-dapps-glue = "1.9"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
parity-dapps-glue = "1.9"
|
|
@ -1,21 +0,0 @@
|
|||||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is part of Parity.
|
|
||||||
|
|
||||||
// Parity is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// Parity is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
extern crate parity_dapps_glue;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
parity_dapps_glue::generate();
|
|
||||||
}
|
|
@ -1,119 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width">
|
|
||||||
<title>Parity</title>
|
|
||||||
<style>
|
|
||||||
/* Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
|
||||||
/* This file is part of Parity.
|
|
||||||
/*
|
|
||||||
/* Parity is free software: you can redistribute it and/or modify
|
|
||||||
/* it under the terms of the GNU General Public License as published by
|
|
||||||
/* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
/* (at your option) any later version.
|
|
||||||
/*
|
|
||||||
/* Parity is distributed in the hope that it will be useful,
|
|
||||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
/* GNU General Public License for more details.
|
|
||||||
/*
|
|
||||||
/* You should have received a copy of the GNU General Public License
|
|
||||||
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
:root, :root body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
border: 0;
|
|
||||||
font-size: 100%;
|
|
||||||
font: inherit;
|
|
||||||
vertical-align: baseline;
|
|
||||||
background: rgb(95, 95, 95);
|
|
||||||
color: rgba(255, 255, 255, 0.75);
|
|
||||||
font-size: 16px;
|
|
||||||
font-family: 'Roboto', sans-serif;
|
|
||||||
font-weight: 300;
|
|
||||||
}
|
|
||||||
|
|
||||||
:root a, :root a:visited {
|
|
||||||
text-decoration: none;
|
|
||||||
cursor: pointer;
|
|
||||||
color: rgb(0, 151, 167); /* #f80 */
|
|
||||||
}
|
|
||||||
|
|
||||||
:root a:hover {
|
|
||||||
color: rgb(0, 174, 193);
|
|
||||||
}
|
|
||||||
|
|
||||||
h1,h2,h3,h4,h5,h6 {
|
|
||||||
font-weight: 300;
|
|
||||||
text-transform: uppercase;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 24px;
|
|
||||||
line-height: 36px;
|
|
||||||
color: rgb(0, 151, 167);
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: 20px;
|
|
||||||
line-height: 34px;
|
|
||||||
}
|
|
||||||
|
|
||||||
code,kbd,pre,samp {
|
|
||||||
font-family: 'Roboto Mono', monospace;
|
|
||||||
}
|
|
||||||
|
|
||||||
.parity-navbar {
|
|
||||||
background: rgb(65, 65, 65);
|
|
||||||
height: 72px;
|
|
||||||
padding: 0 1rem;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.parity-status {
|
|
||||||
clear: both;
|
|
||||||
padding: 1rem;
|
|
||||||
margin: 1rem 0;
|
|
||||||
text-align: right;
|
|
||||||
opacity: 0.75;
|
|
||||||
}
|
|
||||||
|
|
||||||
.parity-box {
|
|
||||||
margin: 1rem;
|
|
||||||
padding: 1rem;
|
|
||||||
background-color: rgb(48, 48, 48);
|
|
||||||
box-sizing: border-box;
|
|
||||||
box-shadow: rgba(0, 0, 0, 0.117647) 0px 1px 6px, rgba(0, 0, 0, 0.117647) 0px 1px 4px;
|
|
||||||
border-radius: 2px;
|
|
||||||
z-index: 1;
|
|
||||||
color: #aaa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.parity-box h1,
|
|
||||||
.parity-box h2,
|
|
||||||
.parity-box h3,
|
|
||||||
.parity-box h4,
|
|
||||||
.parity-box h5,
|
|
||||||
.parity-box h6 {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="parity-navbar">
|
|
||||||
</div>
|
|
||||||
<div class="parity-box">
|
|
||||||
<h1>The Parity UI has been split off into a standalone project.</h1>
|
|
||||||
<h3>Get the standalone Parity UI from <a href="https://github.com/Parity-JS/shell/releases">here</a></h3>
|
|
||||||
<p>
|
|
||||||
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="parity-status">
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,21 +0,0 @@
|
|||||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is part of Parity.
|
|
||||||
|
|
||||||
// Parity is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// Parity is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#[cfg(feature = "with-syntex")]
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/lib.rs"));
|
|
||||||
|
|
||||||
#[cfg(not(feature = "with-syntex"))]
|
|
||||||
include!("lib.rs.in");
|
|
@ -1,55 +0,0 @@
|
|||||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is part of Parity.
|
|
||||||
|
|
||||||
// Parity is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// Parity is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
extern crate parity_dapps_glue;
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use parity_dapps_glue::{WebApp, File, Info};
|
|
||||||
|
|
||||||
#[derive(WebAppFiles)]
|
|
||||||
#[webapp(path = "../build")]
|
|
||||||
pub struct App {
|
|
||||||
pub files: HashMap<&'static str, File>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for App {
|
|
||||||
fn default() -> App {
|
|
||||||
App {
|
|
||||||
files: Self::files(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WebApp for App {
|
|
||||||
fn file(&self, path: &str) -> Option<&File> {
|
|
||||||
self.files.get(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn info(&self) -> Info {
|
|
||||||
Info {
|
|
||||||
name: "Parity Wallet info page",
|
|
||||||
version: env!("CARGO_PKG_VERSION"),
|
|
||||||
author: "Parity <admin@parity.io>",
|
|
||||||
description: "Deprecation notice for Parity Wallet",
|
|
||||||
icon_url: "icon.png",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_js() {
|
|
||||||
parity_dapps_glue::js::build(env!("CARGO_MANIFEST_DIR"), "build");
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
[package]
|
|
||||||
description = "Ethcore Parity UI"
|
|
||||||
homepage = "http://parity.io"
|
|
||||||
license = "GPL-3.0"
|
|
||||||
name = "parity-ui"
|
|
||||||
version = "1.12.0"
|
|
||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
rustc_version = "0.2"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
parity-ui-dev = { git = "https://github.com/parity-js/shell.git", rev = "eecaadcb9e421bce31e91680d14a20bbd38f92a2", optional = true }
|
|
||||||
parity-ui-old-dev = { git = "https://github.com/parity-js/dapp-wallet.git", rev = "65deb02e7c007a0fd8aab0c089c93e3fd1de6f87", optional = true }
|
|
||||||
parity-ui-precompiled = { git = "https://github.com/js-dist-paritytech/parity-master-1-10-shell.git", rev="bd25b41cd642c6b822d820dded3aa601a29aa079", optional = true }
|
|
||||||
parity-ui-old-precompiled = { git = "https://github.com/js-dist-paritytech/parity-master-1-10-wallet.git", rev="4b6f112412716cd05123d32eeb7fda448288a6c6", optional = true }
|
|
||||||
|
|
||||||
[features]
|
|
||||||
no-precompiled-js = ["parity-ui-dev", "parity-ui-old-dev"]
|
|
||||||
use-precompiled-js = ["parity-ui-precompiled", "parity-ui-old-precompiled"]
|
|
@ -1,45 +0,0 @@
|
|||||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is part of Parity.
|
|
||||||
|
|
||||||
// Parity is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// Parity is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#[cfg(feature = "parity-ui-dev")]
|
|
||||||
mod inner {
|
|
||||||
extern crate parity_ui_dev;
|
|
||||||
|
|
||||||
pub use self::parity_ui_dev::*;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "parity-ui-precompiled")]
|
|
||||||
mod inner {
|
|
||||||
extern crate parity_ui_precompiled;
|
|
||||||
|
|
||||||
pub use self::parity_ui_precompiled::*;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "parity-ui-old-dev")]
|
|
||||||
pub mod old {
|
|
||||||
extern crate parity_ui_old_dev;
|
|
||||||
|
|
||||||
pub use self::parity_ui_old_dev::*;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "parity-ui-old-precompiled")]
|
|
||||||
pub mod old {
|
|
||||||
extern crate parity_ui_old_precompiled;
|
|
||||||
|
|
||||||
pub use self::parity_ui_old_precompiled::*;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub use self::inner::*;
|
|
@ -26,10 +26,6 @@ usage! {
|
|||||||
// Arguments must start with arg_
|
// Arguments must start with arg_
|
||||||
// Flags must start with flag_
|
// Flags must start with flag_
|
||||||
|
|
||||||
CMD cmd_ui {
|
|
||||||
"Manage ui",
|
|
||||||
}
|
|
||||||
|
|
||||||
CMD cmd_dapp
|
CMD cmd_dapp
|
||||||
{
|
{
|
||||||
"Manage dapps",
|
"Manage dapps",
|
||||||
@ -376,35 +372,10 @@ usage! {
|
|||||||
"Provide a file containing passwords for unlocking accounts (signer, private account, validators).",
|
"Provide a file containing passwords for unlocking accounts (signer, private account, validators).",
|
||||||
|
|
||||||
["UI options"]
|
["UI options"]
|
||||||
FLAG flag_force_ui: (bool) = false, or |c: &Config| c.ui.as_ref()?.force.clone(),
|
|
||||||
"--force-ui",
|
|
||||||
"Enable Trusted UI WebSocket endpoint, even when --unlock is in use.",
|
|
||||||
|
|
||||||
FLAG flag_no_ui: (bool) = false, or |c: &Config| c.ui.as_ref()?.disable.clone(),
|
|
||||||
"--no-ui",
|
|
||||||
"Disable Trusted UI WebSocket endpoint.",
|
|
||||||
|
|
||||||
// NOTE [todr] For security reasons don't put this to config files
|
|
||||||
FLAG flag_ui_no_validation: (bool) = false, or |_| None,
|
|
||||||
"--ui-no-validation",
|
|
||||||
"Disable Origin and Host headers validation for Trusted UI. WARNING: INSECURE. Used only for development.",
|
|
||||||
|
|
||||||
ARG arg_ui_interface: (String) = "local", or |c: &Config| c.ui.as_ref()?.interface.clone(),
|
|
||||||
"--ui-interface=[IP]",
|
|
||||||
"Specify the hostname portion of the Trusted UI server, IP should be an interface's IP address, or local.",
|
|
||||||
|
|
||||||
ARG arg_ui_hosts: (String) = "none", or |c: &Config| c.ui.as_ref()?.hosts.as_ref().map(|vec| vec.join(",")),
|
|
||||||
"--ui-hosts=[HOSTS]",
|
|
||||||
"List of allowed Host header values. This option will validate the Host header sent by the browser, it is additional security against some attack vectors. Special options: \"all\", \"none\",.",
|
|
||||||
|
|
||||||
ARG arg_ui_path: (String) = "$BASE/signer", or |c: &Config| c.ui.as_ref()?.path.clone(),
|
ARG arg_ui_path: (String) = "$BASE/signer", or |c: &Config| c.ui.as_ref()?.path.clone(),
|
||||||
"--ui-path=[PATH]",
|
"--ui-path=[PATH]",
|
||||||
"Specify directory where Trusted UIs tokens should be stored.",
|
"Specify directory where Trusted UIs tokens should be stored.",
|
||||||
|
|
||||||
ARG arg_ui_port: (u16) = 8180u16, or |c: &Config| c.ui.as_ref()?.port.clone(),
|
|
||||||
"--ui-port=[PORT]",
|
|
||||||
"Specify the port of Trusted UI server.",
|
|
||||||
|
|
||||||
["Networking options"]
|
["Networking options"]
|
||||||
FLAG flag_no_warp: (bool) = false, or |c: &Config| c.network.as_ref()?.warp.clone().map(|w| !w),
|
FLAG flag_no_warp: (bool) = false, or |c: &Config| c.network.as_ref()?.warp.clone().map(|w| !w),
|
||||||
"--no-warp",
|
"--no-warp",
|
||||||
@ -948,6 +919,30 @@ usage! {
|
|||||||
"--public-node",
|
"--public-node",
|
||||||
"Does nothing; Public node is removed from Parity.",
|
"Does nothing; Public node is removed from Parity.",
|
||||||
|
|
||||||
|
FLAG flag_force_ui: (bool) = false, or |_| None,
|
||||||
|
"--force-ui",
|
||||||
|
"Does nothing; UI is now a separate project.",
|
||||||
|
|
||||||
|
FLAG flag_no_ui: (bool) = false, or |_| None,
|
||||||
|
"--no-ui",
|
||||||
|
"Does nothing; UI is now a separate project.",
|
||||||
|
|
||||||
|
FLAG flag_ui_no_validation: (bool) = false, or |_| None,
|
||||||
|
"--ui-no-validation",
|
||||||
|
"Does nothing; UI is now a separate project.",
|
||||||
|
|
||||||
|
ARG arg_ui_interface: (String) = "local", or |_| None,
|
||||||
|
"--ui-interface=[IP]",
|
||||||
|
"Does nothing; UI is now a separate project.",
|
||||||
|
|
||||||
|
ARG arg_ui_hosts: (String) = "none", or |_| None,
|
||||||
|
"--ui-hosts=[HOSTS]",
|
||||||
|
"Does nothing; UI is now a separate project.",
|
||||||
|
|
||||||
|
ARG arg_ui_port: (u16) = 8180u16, or |_| None,
|
||||||
|
"--ui-port=[PORT]",
|
||||||
|
"Does nothing; UI is now a separate project.",
|
||||||
|
|
||||||
ARG arg_dapps_port: (Option<u16>) = None, or |c: &Config| c.dapps.as_ref()?.port.clone(),
|
ARG arg_dapps_port: (Option<u16>) = None, or |c: &Config| c.dapps.as_ref()?.port.clone(),
|
||||||
"--dapps-port=[PORT]",
|
"--dapps-port=[PORT]",
|
||||||
"Dapps server is merged with RPC server. Use --jsonrpc-port.",
|
"Dapps server is merged with RPC server. Use --jsonrpc-port.",
|
||||||
@ -1111,12 +1106,18 @@ struct PrivateTransactions {
|
|||||||
#[derive(Default, Debug, PartialEq, Deserialize)]
|
#[derive(Default, Debug, PartialEq, Deserialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
struct Ui {
|
struct Ui {
|
||||||
force: Option<bool>,
|
|
||||||
disable: Option<bool>,
|
|
||||||
port: Option<u16>,
|
|
||||||
interface: Option<String>,
|
|
||||||
hosts: Option<Vec<String>>,
|
|
||||||
path: Option<String>,
|
path: Option<String>,
|
||||||
|
|
||||||
|
#[serde(rename="force")]
|
||||||
|
_legacy_force: Option<bool>,
|
||||||
|
#[serde(rename="disable")]
|
||||||
|
_legacy_disable: Option<bool>,
|
||||||
|
#[serde(rename="port")]
|
||||||
|
_legacy_port: Option<u16>,
|
||||||
|
#[serde(rename="interface")]
|
||||||
|
_legacy_interface: Option<String>,
|
||||||
|
#[serde(rename="hosts")]
|
||||||
|
_legacy_hosts: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, PartialEq, Deserialize)]
|
#[derive(Default, Debug, PartialEq, Deserialize)]
|
||||||
@ -1404,15 +1405,13 @@ mod tests {
|
|||||||
let args = Args::parse(&["parity", "--secretstore-nodes", "abc@127.0.0.1:3333,cde@10.10.10.10:4444"]).unwrap();
|
let args = Args::parse(&["parity", "--secretstore-nodes", "abc@127.0.0.1:3333,cde@10.10.10.10:4444"]).unwrap();
|
||||||
assert_eq!(args.arg_secretstore_nodes, "abc@127.0.0.1:3333,cde@10.10.10.10:4444");
|
assert_eq!(args.arg_secretstore_nodes, "abc@127.0.0.1:3333,cde@10.10.10.10:4444");
|
||||||
|
|
||||||
let args = Args::parse(&["parity", "--password", "~/.safe/1", "--password", "~/.safe/2", "--ui-port", "8123", "ui"]).unwrap();
|
let args = Args::parse(&["parity", "--password", "~/.safe/1", "--password", "~/.safe/2", "--ui-port", "8123"]).unwrap();
|
||||||
assert_eq!(args.arg_password, vec!["~/.safe/1".to_owned(), "~/.safe/2".to_owned()]);
|
assert_eq!(args.arg_password, vec!["~/.safe/1".to_owned(), "~/.safe/2".to_owned()]);
|
||||||
assert_eq!(args.arg_ui_port, 8123);
|
assert_eq!(args.arg_ui_port, 8123);
|
||||||
assert_eq!(args.cmd_ui, true);
|
|
||||||
|
|
||||||
let args = Args::parse(&["parity", "--password", "~/.safe/1,~/.safe/2", "--ui-port", "8123", "ui"]).unwrap();
|
let args = Args::parse(&["parity", "--password", "~/.safe/1,~/.safe/2", "--ui-port", "8123"]).unwrap();
|
||||||
assert_eq!(args.arg_password, vec!["~/.safe/1".to_owned(), "~/.safe/2".to_owned()]);
|
assert_eq!(args.arg_password, vec!["~/.safe/1".to_owned(), "~/.safe/2".to_owned()]);
|
||||||
assert_eq!(args.arg_ui_port, 8123);
|
assert_eq!(args.arg_ui_port, 8123);
|
||||||
assert_eq!(args.cmd_ui, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1476,7 +1475,6 @@ mod tests {
|
|||||||
// then
|
// then
|
||||||
assert_eq!(args, Args {
|
assert_eq!(args, Args {
|
||||||
// Commands
|
// Commands
|
||||||
cmd_ui: false,
|
|
||||||
cmd_dapp: false,
|
cmd_dapp: false,
|
||||||
cmd_daemon: false,
|
cmd_daemon: false,
|
||||||
cmd_account: false,
|
cmd_account: false,
|
||||||
@ -1566,7 +1564,7 @@ mod tests {
|
|||||||
flag_force_ui: false,
|
flag_force_ui: false,
|
||||||
flag_no_ui: false,
|
flag_no_ui: false,
|
||||||
arg_ui_port: 8180u16,
|
arg_ui_port: 8180u16,
|
||||||
arg_ui_interface: "127.0.0.1".into(),
|
arg_ui_interface: "local".into(),
|
||||||
arg_ui_hosts: "none".into(),
|
arg_ui_hosts: "none".into(),
|
||||||
arg_ui_path: "$HOME/.parity/signer".into(),
|
arg_ui_path: "$HOME/.parity/signer".into(),
|
||||||
flag_ui_no_validation: false,
|
flag_ui_no_validation: false,
|
||||||
@ -1820,12 +1818,12 @@ mod tests {
|
|||||||
fast_unlock: None,
|
fast_unlock: None,
|
||||||
}),
|
}),
|
||||||
ui: Some(Ui {
|
ui: Some(Ui {
|
||||||
force: None,
|
|
||||||
disable: Some(true),
|
|
||||||
port: None,
|
|
||||||
interface: None,
|
|
||||||
hosts: None,
|
|
||||||
path: None,
|
path: None,
|
||||||
|
_legacy_force: None,
|
||||||
|
_legacy_disable: Some(true),
|
||||||
|
_legacy_port: None,
|
||||||
|
_legacy_interface: None,
|
||||||
|
_legacy_hosts: None,
|
||||||
}),
|
}),
|
||||||
network: Some(Network {
|
network: Some(Network {
|
||||||
warp: Some(false),
|
warp: Some(false),
|
||||||
|
@ -20,7 +20,6 @@ use std::net::SocketAddr;
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::str::FromStr;
|
|
||||||
use cli::{Args, ArgsError};
|
use cli::{Args, ArgsError};
|
||||||
use hash::keccak;
|
use hash::keccak;
|
||||||
use ethereum_types::{U256, H256, Address};
|
use ethereum_types::{U256, H256, Address};
|
||||||
@ -34,7 +33,7 @@ use ethcore::miner::{stratum, MinerOptions};
|
|||||||
use ethcore::verification::queue::VerifierSettings;
|
use ethcore::verification::queue::VerifierSettings;
|
||||||
use miner::pool;
|
use miner::pool;
|
||||||
|
|
||||||
use rpc::{IpcConfiguration, HttpConfiguration, WsConfiguration, UiConfiguration};
|
use rpc::{IpcConfiguration, HttpConfiguration, WsConfiguration};
|
||||||
use parity_rpc::NetworkSettings;
|
use parity_rpc::NetworkSettings;
|
||||||
use cache::CacheConfig;
|
use cache::CacheConfig;
|
||||||
use helpers::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_price, geth_ipc_path, parity_ipc_path, to_bootnodes, to_addresses, to_address, to_queue_strategy, to_queue_penalization, passwords_from_files};
|
use helpers::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_price, geth_ipc_path, parity_ipc_path, to_bootnodes, to_addresses, to_address, to_queue_strategy, to_queue_penalization, passwords_from_files};
|
||||||
@ -65,7 +64,7 @@ pub enum Cmd {
|
|||||||
Account(AccountCmd),
|
Account(AccountCmd),
|
||||||
ImportPresaleWallet(ImportWallet),
|
ImportPresaleWallet(ImportWallet),
|
||||||
Blockchain(BlockchainCmd),
|
Blockchain(BlockchainCmd),
|
||||||
SignerToken(WsConfiguration, UiConfiguration, LogConfig),
|
SignerToken(WsConfiguration, LogConfig),
|
||||||
SignerSign {
|
SignerSign {
|
||||||
id: Option<usize>,
|
id: Option<usize>,
|
||||||
pwfile: Option<PathBuf>,
|
pwfile: Option<PathBuf>,
|
||||||
@ -130,7 +129,6 @@ impl Configuration {
|
|||||||
let http_conf = self.http_config()?;
|
let http_conf = self.http_config()?;
|
||||||
let ipc_conf = self.ipc_config()?;
|
let ipc_conf = self.ipc_config()?;
|
||||||
let net_conf = self.net_config()?;
|
let net_conf = self.net_config()?;
|
||||||
let ui_conf = self.ui_config();
|
|
||||||
let network_id = self.network_id();
|
let network_id = self.network_id();
|
||||||
let cache_config = self.cache_config();
|
let cache_config = self.cache_config();
|
||||||
let tracing = self.args.arg_tracing.parse()?;
|
let tracing = self.args.arg_tracing.parse()?;
|
||||||
@ -150,7 +148,7 @@ impl Configuration {
|
|||||||
let authfile = ::signer::codes_path(&ws_conf.signer_path);
|
let authfile = ::signer::codes_path(&ws_conf.signer_path);
|
||||||
|
|
||||||
if self.args.cmd_signer_new_token {
|
if self.args.cmd_signer_new_token {
|
||||||
Cmd::SignerToken(ws_conf, ui_conf, logger_config.clone())
|
Cmd::SignerToken(ws_conf, logger_config.clone())
|
||||||
} else if self.args.cmd_signer_sign {
|
} else if self.args.cmd_signer_sign {
|
||||||
let pwfile = self.accounts_config()?.password_files.first().map(|pwfile| {
|
let pwfile = self.accounts_config()?.password_files.first().map(|pwfile| {
|
||||||
PathBuf::from(pwfile)
|
PathBuf::from(pwfile)
|
||||||
@ -381,13 +379,11 @@ impl Configuration {
|
|||||||
net_settings: self.network_settings()?,
|
net_settings: self.network_settings()?,
|
||||||
dapps_conf: dapps_conf,
|
dapps_conf: dapps_conf,
|
||||||
ipfs_conf: ipfs_conf,
|
ipfs_conf: ipfs_conf,
|
||||||
ui_conf: ui_conf,
|
|
||||||
secretstore_conf: secretstore_conf,
|
secretstore_conf: secretstore_conf,
|
||||||
private_provider_conf: private_provider_conf,
|
private_provider_conf: private_provider_conf,
|
||||||
private_encryptor_conf: private_enc_conf,
|
private_encryptor_conf: private_enc_conf,
|
||||||
private_tx_enabled,
|
private_tx_enabled,
|
||||||
dapp: self.dapp_to_open()?,
|
dapp: self.dapp_to_open()?,
|
||||||
ui: self.args.cmd_ui,
|
|
||||||
name: self.args.arg_identity,
|
name: self.args.arg_identity,
|
||||||
custom_bootnodes: self.args.arg_bootnodes.is_some(),
|
custom_bootnodes: self.args.arg_bootnodes.is_some(),
|
||||||
no_periodic_snapshot: self.args.flag_no_periodic_snapshot,
|
no_periodic_snapshot: self.args.flag_no_periodic_snapshot,
|
||||||
@ -588,29 +584,11 @@ impl Configuration {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ui_port(&self) -> u16 {
|
|
||||||
self.args.arg_ports_shift + self.args.arg_ui_port
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ntp_servers(&self) -> Vec<String> {
|
fn ntp_servers(&self) -> Vec<String> {
|
||||||
self.args.arg_ntp_servers.split(",").map(str::to_owned).collect()
|
self.args.arg_ntp_servers.split(",").map(str::to_owned).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ui_config(&self) -> UiConfiguration {
|
|
||||||
let ui = self.ui_enabled();
|
|
||||||
UiConfiguration {
|
|
||||||
enabled: ui.enabled,
|
|
||||||
interface: self.ui_interface(),
|
|
||||||
port: self.ui_port(),
|
|
||||||
hosts: self.ui_hosts(),
|
|
||||||
info_page_only: ui.info_page_only,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dapps_config(&self) -> DappsConfiguration {
|
fn dapps_config(&self) -> DappsConfiguration {
|
||||||
let dev_ui = if self.args.flag_ui_no_validation { vec![("127.0.0.1".to_owned(), 3000)] } else { vec![] };
|
|
||||||
let ui_port = self.ui_port();
|
|
||||||
|
|
||||||
DappsConfiguration {
|
DappsConfiguration {
|
||||||
enabled: self.dapps_enabled(),
|
enabled: self.dapps_enabled(),
|
||||||
dapps_path: PathBuf::from(self.directories().dapps),
|
dapps_path: PathBuf::from(self.directories().dapps),
|
||||||
@ -619,31 +597,6 @@ impl Configuration {
|
|||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
},
|
},
|
||||||
extra_embed_on: {
|
|
||||||
let mut extra_embed = dev_ui.clone();
|
|
||||||
match self.ui_hosts() {
|
|
||||||
// In case host validation is disabled allow all frame ancestors
|
|
||||||
None => {
|
|
||||||
// NOTE Chrome does not seem to support "*:<port>"
|
|
||||||
// we use `http(s)://*:<port>` instead.
|
|
||||||
extra_embed.push(("http://*".to_owned(), ui_port));
|
|
||||||
extra_embed.push(("https://*".to_owned(), ui_port));
|
|
||||||
},
|
|
||||||
Some(hosts) => extra_embed.extend(hosts.into_iter().filter_map(|host| {
|
|
||||||
let mut it = host.split(":");
|
|
||||||
let host = it.next();
|
|
||||||
let port = it.next().and_then(|v| u16::from_str(v).ok());
|
|
||||||
|
|
||||||
match (host, port) {
|
|
||||||
(Some(host), Some(port)) => Some((host.into(), port)),
|
|
||||||
(Some(host), None) => Some((host.into(), ui_port)),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
})),
|
|
||||||
}
|
|
||||||
extra_embed
|
|
||||||
},
|
|
||||||
extra_script_src: dev_ui,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -863,10 +816,6 @@ impl Configuration {
|
|||||||
Some(hosts)
|
Some(hosts)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ui_hosts(&self) -> Option<Vec<String>> {
|
|
||||||
self.hosts(&self.args.arg_ui_hosts, &self.ui_interface())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rpc_hosts(&self) -> Option<Vec<String>> {
|
fn rpc_hosts(&self) -> Option<Vec<String>> {
|
||||||
self.hosts(&self.args.arg_jsonrpc_hosts, &self.rpc_interface())
|
self.hosts(&self.args.arg_jsonrpc_hosts, &self.rpc_interface())
|
||||||
}
|
}
|
||||||
@ -876,7 +825,7 @@ impl Configuration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn ws_origins(&self) -> Option<Vec<String>> {
|
fn ws_origins(&self) -> Option<Vec<String>> {
|
||||||
if self.args.flag_unsafe_expose || self.args.flag_ui_no_validation {
|
if self.args.flag_unsafe_expose {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -925,7 +874,6 @@ impl Configuration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn ws_config(&self) -> Result<WsConfiguration, String> {
|
fn ws_config(&self) -> Result<WsConfiguration, String> {
|
||||||
let ui = self.ui_config();
|
|
||||||
let http = self.http_config()?;
|
let http = self.http_config()?;
|
||||||
|
|
||||||
let support_token_api =
|
let support_token_api =
|
||||||
@ -941,7 +889,6 @@ impl Configuration {
|
|||||||
origins: self.ws_origins(),
|
origins: self.ws_origins(),
|
||||||
signer_path: self.directories().signer.into(),
|
signer_path: self.directories().signer.into(),
|
||||||
support_token_api,
|
support_token_api,
|
||||||
ui_address: ui.address(),
|
|
||||||
dapps_address: http.address(),
|
dapps_address: http.address(),
|
||||||
max_connections: self.args.arg_ws_max_connections,
|
max_connections: self.args.arg_ws_max_connections,
|
||||||
};
|
};
|
||||||
@ -1065,10 +1012,6 @@ impl Configuration {
|
|||||||
}.into()
|
}.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ui_interface(&self) -> String {
|
|
||||||
self.interface(&self.args.arg_ui_interface)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rpc_interface(&self) -> String {
|
fn rpc_interface(&self) -> String {
|
||||||
let rpc_interface = self.args.arg_rpcaddr.clone().unwrap_or(self.args.arg_jsonrpc_interface.clone());
|
let rpc_interface = self.args.arg_rpcaddr.clone().unwrap_or(self.args.arg_jsonrpc_interface.clone());
|
||||||
self.interface(&rpc_interface)
|
self.interface(&rpc_interface)
|
||||||
@ -1184,24 +1127,6 @@ impl Configuration {
|
|||||||
into_secretstore_service_contract_address(self.args.arg_secretstore_doc_sretr_contract.as_ref())
|
into_secretstore_service_contract_address(self.args.arg_secretstore_doc_sretr_contract.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ui_enabled(&self) -> UiEnabled {
|
|
||||||
if self.args.flag_force_ui {
|
|
||||||
return UiEnabled {
|
|
||||||
enabled: true,
|
|
||||||
info_page_only: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let ui_disabled = self.args.arg_unlock.is_some() ||
|
|
||||||
self.args.flag_geth ||
|
|
||||||
self.args.flag_no_ui;
|
|
||||||
|
|
||||||
return UiEnabled {
|
|
||||||
enabled: (self.args.cmd_ui || !ui_disabled) && cfg!(feature = "ui-enabled"),
|
|
||||||
info_page_only: !self.args.cmd_ui,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verifier_settings(&self) -> VerifierSettings {
|
fn verifier_settings(&self) -> VerifierSettings {
|
||||||
let mut settings = VerifierSettings::default();
|
let mut settings = VerifierSettings::default();
|
||||||
settings.scale_verifiers = self.args.flag_scale_verifiers;
|
settings.scale_verifiers = self.args.flag_scale_verifiers;
|
||||||
@ -1220,12 +1145,6 @@ impl Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
|
||||||
struct UiEnabled {
|
|
||||||
pub enabled: bool,
|
|
||||||
pub info_page_only: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn into_secretstore_service_contract_address(s: &str) -> Result<Option<SecretStoreContractAddress>, String> {
|
fn into_secretstore_service_contract_address(s: &str) -> Result<Option<SecretStoreContractAddress>, String> {
|
||||||
match s {
|
match s {
|
||||||
"none" => Ok(None),
|
"none" => Ok(None),
|
||||||
@ -1254,7 +1173,7 @@ mod tests {
|
|||||||
use helpers::{default_network_config};
|
use helpers::{default_network_config};
|
||||||
use params::SpecType;
|
use params::SpecType;
|
||||||
use presale::ImportWallet;
|
use presale::ImportWallet;
|
||||||
use rpc::{WsConfiguration, UiConfiguration};
|
use rpc::WsConfiguration;
|
||||||
use rpc_apis::ApiSet;
|
use rpc_apis::ApiSet;
|
||||||
use run::RunCmd;
|
use run::RunCmd;
|
||||||
|
|
||||||
@ -1438,16 +1357,9 @@ mod tests {
|
|||||||
origins: Some(vec!["parity://*".into(),"chrome-extension://*".into(), "moz-extension://*".into()]),
|
origins: Some(vec!["parity://*".into(),"chrome-extension://*".into(), "moz-extension://*".into()]),
|
||||||
hosts: Some(vec![]),
|
hosts: Some(vec![]),
|
||||||
signer_path: expected.into(),
|
signer_path: expected.into(),
|
||||||
ui_address: Some("127.0.0.1:8180".into()),
|
|
||||||
dapps_address: Some("127.0.0.1:8545".into()),
|
dapps_address: Some("127.0.0.1:8545".into()),
|
||||||
support_token_api: true,
|
support_token_api: true,
|
||||||
max_connections: 100,
|
max_connections: 100,
|
||||||
}, UiConfiguration {
|
|
||||||
enabled: true,
|
|
||||||
interface: "127.0.0.1".into(),
|
|
||||||
port: 8180,
|
|
||||||
hosts: Some(vec![]),
|
|
||||||
info_page_only: true,
|
|
||||||
}, LogConfig {
|
}, LogConfig {
|
||||||
color: true,
|
color: true,
|
||||||
mode: None,
|
mode: None,
|
||||||
@ -1516,12 +1428,10 @@ mod tests {
|
|||||||
net_settings: Default::default(),
|
net_settings: Default::default(),
|
||||||
dapps_conf: Default::default(),
|
dapps_conf: Default::default(),
|
||||||
ipfs_conf: Default::default(),
|
ipfs_conf: Default::default(),
|
||||||
ui_conf: Default::default(),
|
|
||||||
secretstore_conf: Default::default(),
|
secretstore_conf: Default::default(),
|
||||||
private_provider_conf: Default::default(),
|
private_provider_conf: Default::default(),
|
||||||
private_encryptor_conf: Default::default(),
|
private_encryptor_conf: Default::default(),
|
||||||
private_tx_enabled: false,
|
private_tx_enabled: false,
|
||||||
ui: false,
|
|
||||||
dapp: None,
|
dapp: None,
|
||||||
name: "".into(),
|
name: "".into(),
|
||||||
custom_bootnodes: false,
|
custom_bootnodes: false,
|
||||||
@ -1704,49 +1614,6 @@ mod tests {
|
|||||||
assert_eq!(conf2.ipfs_cors(), Some(vec!["http://parity.io".into(),"http://something.io".into()]));
|
assert_eq!(conf2.ipfs_cors(), Some(vec!["http://parity.io".into(),"http://something.io".into()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_disable_signer_in_geth_compat() {
|
|
||||||
// given
|
|
||||||
|
|
||||||
// when
|
|
||||||
let conf0 = parse(&["parity", "--geth"]);
|
|
||||||
let conf1 = parse(&["parity", "--geth", "--force-ui"]);
|
|
||||||
let conf2 = parse(&["parity", "--geth", "ui"]);
|
|
||||||
let conf3 = parse(&["parity"]);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assert_eq!(conf0.ui_enabled(), UiEnabled {
|
|
||||||
enabled: false,
|
|
||||||
info_page_only: true,
|
|
||||||
});
|
|
||||||
assert_eq!(conf1.ui_enabled(), UiEnabled {
|
|
||||||
enabled: true,
|
|
||||||
info_page_only: false,
|
|
||||||
});
|
|
||||||
assert_eq!(conf2.ui_enabled(), UiEnabled {
|
|
||||||
enabled: true,
|
|
||||||
info_page_only: false,
|
|
||||||
});
|
|
||||||
assert_eq!(conf3.ui_enabled(), UiEnabled {
|
|
||||||
enabled: true,
|
|
||||||
info_page_only: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_disable_signer_when_account_is_unlocked() {
|
|
||||||
// given
|
|
||||||
|
|
||||||
// when
|
|
||||||
let conf0 = parse(&["parity", "--unlock", "0x0"]);
|
|
||||||
|
|
||||||
// then
|
|
||||||
assert_eq!(conf0.ui_enabled(), UiEnabled {
|
|
||||||
enabled: false,
|
|
||||||
info_page_only: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_parse_ui_configuration() {
|
fn should_parse_ui_configuration() {
|
||||||
// given
|
// given
|
||||||
@ -1757,69 +1624,22 @@ mod tests {
|
|||||||
let conf2 = parse(&["parity", "--ui-path=signer", "--ui-port", "3123"]);
|
let conf2 = parse(&["parity", "--ui-path=signer", "--ui-port", "3123"]);
|
||||||
let conf3 = parse(&["parity", "--ui-path=signer", "--ui-interface", "test"]);
|
let conf3 = parse(&["parity", "--ui-path=signer", "--ui-interface", "test"]);
|
||||||
let conf4 = parse(&["parity", "--ui-path=signer", "--force-ui"]);
|
let conf4 = parse(&["parity", "--ui-path=signer", "--force-ui"]);
|
||||||
let conf5 = parse(&["parity", "--ui-path=signer", "ui"]);
|
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(conf0.directories().signer, "signer".to_owned());
|
assert_eq!(conf0.directories().signer, "signer".to_owned());
|
||||||
assert_eq!(conf0.ui_config(), UiConfiguration {
|
|
||||||
enabled: true,
|
|
||||||
interface: "127.0.0.1".into(),
|
|
||||||
port: 8180,
|
|
||||||
hosts: Some(vec![]),
|
|
||||||
info_page_only: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
assert!(conf1.ws_config().unwrap().hosts.is_some());
|
assert!(conf1.ws_config().unwrap().hosts.is_some());
|
||||||
assert_eq!(conf1.ws_config().unwrap().origins, None);
|
assert_eq!(conf1.ws_config().unwrap().origins, Some(vec!["parity://*".into(), "chrome-extension://*".into(), "moz-extension://*".into()]));
|
||||||
assert_eq!(conf1.directories().signer, "signer".to_owned());
|
assert_eq!(conf1.directories().signer, "signer".to_owned());
|
||||||
assert_eq!(conf1.ui_config(), UiConfiguration {
|
|
||||||
enabled: true,
|
|
||||||
interface: "127.0.0.1".into(),
|
|
||||||
port: 8180,
|
|
||||||
hosts: Some(vec![]),
|
|
||||||
info_page_only: true,
|
|
||||||
});
|
|
||||||
assert_eq!(conf1.dapps_config().extra_embed_on, vec![("127.0.0.1".to_owned(), 3000)]);
|
|
||||||
|
|
||||||
assert!(conf2.ws_config().unwrap().hosts.is_some());
|
assert!(conf2.ws_config().unwrap().hosts.is_some());
|
||||||
assert_eq!(conf2.directories().signer, "signer".to_owned());
|
assert_eq!(conf2.directories().signer, "signer".to_owned());
|
||||||
assert_eq!(conf2.ui_config(), UiConfiguration {
|
|
||||||
enabled: true,
|
|
||||||
interface: "127.0.0.1".into(),
|
|
||||||
port: 3123,
|
|
||||||
hosts: Some(vec![]),
|
|
||||||
info_page_only: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
assert!(conf3.ws_config().unwrap().hosts.is_some());
|
assert!(conf3.ws_config().unwrap().hosts.is_some());
|
||||||
assert_eq!(conf3.directories().signer, "signer".to_owned());
|
assert_eq!(conf3.directories().signer, "signer".to_owned());
|
||||||
assert_eq!(conf3.ui_config(), UiConfiguration {
|
|
||||||
enabled: true,
|
|
||||||
interface: "test".into(),
|
|
||||||
port: 8180,
|
|
||||||
hosts: Some(vec![]),
|
|
||||||
info_page_only: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
assert!(conf4.ws_config().unwrap().hosts.is_some());
|
assert!(conf4.ws_config().unwrap().hosts.is_some());
|
||||||
assert_eq!(conf4.directories().signer, "signer".to_owned());
|
assert_eq!(conf4.directories().signer, "signer".to_owned());
|
||||||
assert_eq!(conf4.ui_config(), UiConfiguration {
|
|
||||||
enabled: true,
|
|
||||||
interface: "127.0.0.1".into(),
|
|
||||||
port: 8180,
|
|
||||||
hosts: Some(vec![]),
|
|
||||||
info_page_only: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
assert!(conf5.ws_config().unwrap().hosts.is_some());
|
|
||||||
assert_eq!(conf5.directories().signer, "signer".to_owned());
|
|
||||||
assert_eq!(conf5.ui_config(), UiConfiguration {
|
|
||||||
enabled: true,
|
|
||||||
interface: "127.0.0.1".into(),
|
|
||||||
port: 8180,
|
|
||||||
hosts: Some(vec![]),
|
|
||||||
info_page_only: false,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1976,7 +1796,6 @@ mod tests {
|
|||||||
assert_eq!(conf0.network_settings().unwrap().rpc_port, 8546);
|
assert_eq!(conf0.network_settings().unwrap().rpc_port, 8546);
|
||||||
assert_eq!(conf0.http_config().unwrap().port, 8546);
|
assert_eq!(conf0.http_config().unwrap().port, 8546);
|
||||||
assert_eq!(conf0.ws_config().unwrap().port, 8547);
|
assert_eq!(conf0.ws_config().unwrap().port, 8547);
|
||||||
assert_eq!(conf0.ui_config().port, 8181);
|
|
||||||
assert_eq!(conf0.secretstore_config().unwrap().port, 8084);
|
assert_eq!(conf0.secretstore_config().unwrap().port, 8084);
|
||||||
assert_eq!(conf0.secretstore_config().unwrap().http_port, 8083);
|
assert_eq!(conf0.secretstore_config().unwrap().http_port, 8083);
|
||||||
assert_eq!(conf0.ipfs_config().port, 5002);
|
assert_eq!(conf0.ipfs_config().port, 5002);
|
||||||
@ -1987,7 +1806,6 @@ mod tests {
|
|||||||
assert_eq!(conf1.network_settings().unwrap().rpc_port, 8545);
|
assert_eq!(conf1.network_settings().unwrap().rpc_port, 8545);
|
||||||
assert_eq!(conf1.http_config().unwrap().port, 8545);
|
assert_eq!(conf1.http_config().unwrap().port, 8545);
|
||||||
assert_eq!(conf1.ws_config().unwrap().port, 8547);
|
assert_eq!(conf1.ws_config().unwrap().port, 8547);
|
||||||
assert_eq!(conf1.ui_config().port, 8181);
|
|
||||||
assert_eq!(conf1.secretstore_config().unwrap().port, 8084);
|
assert_eq!(conf1.secretstore_config().unwrap().port, 8084);
|
||||||
assert_eq!(conf1.secretstore_config().unwrap().http_port, 8083);
|
assert_eq!(conf1.secretstore_config().unwrap().http_port, 8083);
|
||||||
assert_eq!(conf1.ipfs_config().port, 5002);
|
assert_eq!(conf1.ipfs_config().port, 5002);
|
||||||
@ -2007,8 +1825,6 @@ mod tests {
|
|||||||
assert_eq!(&conf0.ws_config().unwrap().interface, "0.0.0.0");
|
assert_eq!(&conf0.ws_config().unwrap().interface, "0.0.0.0");
|
||||||
assert_eq!(conf0.ws_config().unwrap().hosts, None);
|
assert_eq!(conf0.ws_config().unwrap().hosts, None);
|
||||||
assert_eq!(conf0.ws_config().unwrap().origins, None);
|
assert_eq!(conf0.ws_config().unwrap().origins, None);
|
||||||
assert_eq!(&conf0.ui_config().interface, "0.0.0.0");
|
|
||||||
assert_eq!(conf0.ui_config().hosts, None);
|
|
||||||
assert_eq!(&conf0.secretstore_config().unwrap().interface, "0.0.0.0");
|
assert_eq!(&conf0.secretstore_config().unwrap().interface, "0.0.0.0");
|
||||||
assert_eq!(&conf0.secretstore_config().unwrap().http_interface, "0.0.0.0");
|
assert_eq!(&conf0.secretstore_config().unwrap().http_interface, "0.0.0.0");
|
||||||
assert_eq!(&conf0.ipfs_config().interface, "0.0.0.0");
|
assert_eq!(&conf0.ipfs_config().interface, "0.0.0.0");
|
||||||
|
@ -39,8 +39,6 @@ pub struct Configuration {
|
|||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub dapps_path: PathBuf,
|
pub dapps_path: PathBuf,
|
||||||
pub extra_dapps: Vec<PathBuf>,
|
pub extra_dapps: Vec<PathBuf>,
|
||||||
pub extra_embed_on: Vec<(String, u16)>,
|
|
||||||
pub extra_script_src: Vec<(String, u16)>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Configuration {
|
impl Default for Configuration {
|
||||||
@ -50,8 +48,6 @@ impl Default for Configuration {
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
dapps_path: replace_home(&data_dir, "$BASE/dapps").into(),
|
dapps_path: replace_home(&data_dir, "$BASE/dapps").into(),
|
||||||
extra_dapps: vec![],
|
extra_dapps: vec![],
|
||||||
extra_embed_on: vec![],
|
|
||||||
extra_script_src: vec![],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -163,8 +159,6 @@ pub struct Dependencies {
|
|||||||
pub fetch: FetchClient,
|
pub fetch: FetchClient,
|
||||||
pub pool: CpuPool,
|
pub pool: CpuPool,
|
||||||
pub signer: Arc<SignerService>,
|
pub signer: Arc<SignerService>,
|
||||||
pub ui_address: Option<(String, u16)>,
|
|
||||||
pub info_page_only: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(configuration: Configuration, deps: Dependencies) -> Result<Option<Middleware>, String> {
|
pub fn new(configuration: Configuration, deps: Dependencies) -> Result<Option<Middleware>, String> {
|
||||||
@ -177,19 +171,6 @@ pub fn new(configuration: Configuration, deps: Dependencies) -> Result<Option<Mi
|
|||||||
configuration.dapps_path,
|
configuration.dapps_path,
|
||||||
configuration.extra_dapps,
|
configuration.extra_dapps,
|
||||||
rpc::DAPPS_DOMAIN,
|
rpc::DAPPS_DOMAIN,
|
||||||
configuration.extra_embed_on,
|
|
||||||
configuration.extra_script_src,
|
|
||||||
).map(Some)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_ui(enabled: bool, deps: Dependencies) -> Result<Option<Middleware>, String> {
|
|
||||||
if !enabled {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
|
|
||||||
server::ui_middleware(
|
|
||||||
deps,
|
|
||||||
rpc::DAPPS_DOMAIN,
|
|
||||||
).map(Some)
|
).map(Some)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,19 +196,10 @@ mod server {
|
|||||||
_dapps_path: PathBuf,
|
_dapps_path: PathBuf,
|
||||||
_extra_dapps: Vec<PathBuf>,
|
_extra_dapps: Vec<PathBuf>,
|
||||||
_dapps_domain: &str,
|
_dapps_domain: &str,
|
||||||
_extra_embed_on: Vec<(String, u16)>,
|
|
||||||
_extra_script_src: Vec<(String, u16)>,
|
|
||||||
) -> Result<Middleware, String> {
|
) -> Result<Middleware, String> {
|
||||||
Err("Your Parity version has been compiled without WebApps support.".into())
|
Err("Your Parity version has been compiled without WebApps support.".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ui_middleware(
|
|
||||||
_deps: Dependencies,
|
|
||||||
_dapps_domain: &str,
|
|
||||||
) -> Result<Middleware, String> {
|
|
||||||
Err("Your Parity version has been compiled without UI support.".into())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn service(_: &Option<Middleware>) -> Option<Arc<rpc_apis::DappsService>> {
|
pub fn service(_: &Option<Middleware>) -> Option<Arc<rpc_apis::DappsService>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -249,8 +221,6 @@ mod server {
|
|||||||
dapps_path: PathBuf,
|
dapps_path: PathBuf,
|
||||||
extra_dapps: Vec<PathBuf>,
|
extra_dapps: Vec<PathBuf>,
|
||||||
dapps_domain: &str,
|
dapps_domain: &str,
|
||||||
extra_embed_on: Vec<(String, u16)>,
|
|
||||||
extra_script_src: Vec<(String, u16)>,
|
|
||||||
) -> Result<Middleware, String> {
|
) -> Result<Middleware, String> {
|
||||||
let signer = deps.signer;
|
let signer = deps.signer;
|
||||||
let web_proxy_tokens = Arc::new(move |token| signer.web_proxy_access_token_domain(&token));
|
let web_proxy_tokens = Arc::new(move |token| signer.web_proxy_access_token_domain(&token));
|
||||||
@ -258,9 +228,6 @@ mod server {
|
|||||||
Ok(parity_dapps::Middleware::dapps(
|
Ok(parity_dapps::Middleware::dapps(
|
||||||
deps.pool,
|
deps.pool,
|
||||||
deps.node_health,
|
deps.node_health,
|
||||||
deps.ui_address,
|
|
||||||
extra_embed_on,
|
|
||||||
extra_script_src,
|
|
||||||
dapps_path,
|
dapps_path,
|
||||||
extra_dapps,
|
extra_dapps,
|
||||||
dapps_domain,
|
dapps_domain,
|
||||||
@ -271,21 +238,6 @@ mod server {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ui_middleware(
|
|
||||||
deps: Dependencies,
|
|
||||||
dapps_domain: &str,
|
|
||||||
) -> Result<Middleware, String> {
|
|
||||||
Ok(parity_dapps::Middleware::ui(
|
|
||||||
deps.pool,
|
|
||||||
deps.node_health,
|
|
||||||
dapps_domain,
|
|
||||||
deps.contract_client,
|
|
||||||
deps.sync_status,
|
|
||||||
deps.fetch,
|
|
||||||
deps.info_page_only,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn service(middleware: &Option<Middleware>) -> Option<Arc<rpc_apis::DappsService>> {
|
pub fn service(middleware: &Option<Middleware>) -> Option<Arc<rpc_apis::DappsService>> {
|
||||||
middleware.as_ref().map(|m| Arc::new(DappsServiceWrapper {
|
middleware.as_ref().map(|m| Arc::new(DappsServiceWrapper {
|
||||||
endpoints: m.endpoints().clone(),
|
endpoints: m.endpoints().clone(),
|
||||||
|
@ -118,15 +118,13 @@ mod user_defaults;
|
|||||||
mod whisper;
|
mod whisper;
|
||||||
mod db;
|
mod db;
|
||||||
|
|
||||||
use std::net::{TcpListener};
|
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use ansi_term::Style;
|
|
||||||
use hash::keccak_buffer;
|
use hash::keccak_buffer;
|
||||||
use cli::Args;
|
use cli::Args;
|
||||||
use configuration::{Cmd, Execute};
|
use configuration::{Cmd, Execute};
|
||||||
use deprecated::find_deprecated;
|
use deprecated::find_deprecated;
|
||||||
use ethcore_logger::{Config as LogConfig, setup_log};
|
use ethcore_logger::setup_log;
|
||||||
|
|
||||||
pub use self::configuration::Configuration;
|
pub use self::configuration::Configuration;
|
||||||
pub use self::run::RunningClient;
|
pub use self::run::RunningClient;
|
||||||
@ -195,24 +193,6 @@ fn execute<Cr, Rr>(command: Execute, on_client_rq: Cr, on_updater_rq: Rr) -> Res
|
|||||||
|
|
||||||
match command.cmd {
|
match command.cmd {
|
||||||
Cmd::Run(run_cmd) => {
|
Cmd::Run(run_cmd) => {
|
||||||
if run_cmd.ui_conf.enabled && !run_cmd.ui_conf.info_page_only {
|
|
||||||
warn!("{}", Style::new().bold().paint("Parity browser interface is deprecated. It's going to be removed in the next version, use standalone Parity UI instead."));
|
|
||||||
warn!("{}", Style::new().bold().paint("Standalone Parity UI: https://github.com/Parity-JS/shell/releases"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if run_cmd.ui && run_cmd.dapps_conf.enabled {
|
|
||||||
// Check if Parity is already running
|
|
||||||
let addr = format!("{}:{}", run_cmd.ui_conf.interface, run_cmd.ui_conf.port);
|
|
||||||
if !TcpListener::bind(&addr as &str).is_ok() {
|
|
||||||
return open_ui(&run_cmd.ws_conf, &run_cmd.ui_conf, &run_cmd.logger_config).map(|_| ExecutionAction::Instant(None));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// start ui
|
|
||||||
if run_cmd.ui {
|
|
||||||
open_ui(&run_cmd.ws_conf, &run_cmd.ui_conf, &run_cmd.logger_config)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(ref dapp) = run_cmd.dapp {
|
if let Some(ref dapp) = run_cmd.dapp {
|
||||||
open_dapp(&run_cmd.dapps_conf, &run_cmd.http_conf, dapp)?;
|
open_dapp(&run_cmd.dapps_conf, &run_cmd.http_conf, dapp)?;
|
||||||
}
|
}
|
||||||
@ -225,7 +205,7 @@ fn execute<Cr, Rr>(command: Execute, on_client_rq: Cr, on_updater_rq: Rr) -> Res
|
|||||||
Cmd::Account(account_cmd) => account::execute(account_cmd).map(|s| ExecutionAction::Instant(Some(s))),
|
Cmd::Account(account_cmd) => account::execute(account_cmd).map(|s| ExecutionAction::Instant(Some(s))),
|
||||||
Cmd::ImportPresaleWallet(presale_cmd) => presale::execute(presale_cmd).map(|s| ExecutionAction::Instant(Some(s))),
|
Cmd::ImportPresaleWallet(presale_cmd) => presale::execute(presale_cmd).map(|s| ExecutionAction::Instant(Some(s))),
|
||||||
Cmd::Blockchain(blockchain_cmd) => blockchain::execute(blockchain_cmd).map(|_| ExecutionAction::Instant(None)),
|
Cmd::Blockchain(blockchain_cmd) => blockchain::execute(blockchain_cmd).map(|_| ExecutionAction::Instant(None)),
|
||||||
Cmd::SignerToken(ws_conf, ui_conf, logger_config) => signer::execute(ws_conf, ui_conf, logger_config).map(|s| ExecutionAction::Instant(Some(s))),
|
Cmd::SignerToken(ws_conf, logger_config) => signer::execute(ws_conf, logger_config).map(|s| ExecutionAction::Instant(Some(s))),
|
||||||
Cmd::SignerSign { id, pwfile, port, authfile } => rpc_cli::signer_sign(id, pwfile, port, authfile).map(|s| ExecutionAction::Instant(Some(s))),
|
Cmd::SignerSign { id, pwfile, port, authfile } => rpc_cli::signer_sign(id, pwfile, port, authfile).map(|s| ExecutionAction::Instant(Some(s))),
|
||||||
Cmd::SignerList { port, authfile } => rpc_cli::signer_list(port, authfile).map(|s| ExecutionAction::Instant(Some(s))),
|
Cmd::SignerList { port, authfile } => rpc_cli::signer_list(port, authfile).map(|s| ExecutionAction::Instant(Some(s))),
|
||||||
Cmd::SignerReject { id, port, authfile } => rpc_cli::signer_reject(id, port, authfile).map(|s| ExecutionAction::Instant(Some(s))),
|
Cmd::SignerReject { id, port, authfile } => rpc_cli::signer_reject(id, port, authfile).map(|s| ExecutionAction::Instant(Some(s))),
|
||||||
@ -257,19 +237,6 @@ pub fn start<Cr, Rr>(conf: Configuration, on_client_rq: Cr, on_updater_rq: Rr) -
|
|||||||
execute(conf.into_command()?, on_client_rq, on_updater_rq)
|
execute(conf.into_command()?, on_client_rq, on_updater_rq)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_ui(ws_conf: &rpc::WsConfiguration, ui_conf: &rpc::UiConfiguration, logger_config: &LogConfig) -> Result<(), String> {
|
|
||||||
if !ui_conf.enabled {
|
|
||||||
return Err("Cannot use UI command with UI turned off.".into())
|
|
||||||
}
|
|
||||||
|
|
||||||
let token = signer::generate_token_and_url(ws_conf, ui_conf, logger_config)?;
|
|
||||||
// Open a browser
|
|
||||||
url::open(&token.url).map_err(|e| format!("{}", e))?;
|
|
||||||
// Print a message
|
|
||||||
println!("{}", token.message);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn open_dapp(dapps_conf: &dapps::Configuration, rpc_conf: &rpc::HttpConfiguration, dapp: &str) -> Result<(), String> {
|
fn open_dapp(dapps_conf: &dapps::Configuration, rpc_conf: &rpc::HttpConfiguration, dapp: &str) -> Result<(), String> {
|
||||||
if !dapps_conf.enabled {
|
if !dapps_conf.enabled {
|
||||||
return Err("Cannot use DAPP command with Dapps turned off.".into())
|
return Err("Cannot use DAPP command with Dapps turned off.".into())
|
||||||
|
@ -68,58 +68,6 @@ impl Default for HttpConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
|
||||||
pub struct UiConfiguration {
|
|
||||||
pub enabled: bool,
|
|
||||||
pub interface: String,
|
|
||||||
pub port: u16,
|
|
||||||
pub hosts: Option<Vec<String>>,
|
|
||||||
pub info_page_only: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UiConfiguration {
|
|
||||||
pub fn address(&self) -> Option<rpc::Host> {
|
|
||||||
address(self.enabled, &self.interface, self.port, &self.hosts)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn redirection_address(&self) -> Option<(String, u16)> {
|
|
||||||
self.address().map(|host| {
|
|
||||||
let mut it = host.split(':');
|
|
||||||
let hostname: Option<String> = it.next().map(|s| s.to_owned());
|
|
||||||
let port: Option<u16> = it.next().and_then(|s| s.parse().ok());
|
|
||||||
|
|
||||||
(hostname.unwrap_or_else(|| "localhost".into()), port.unwrap_or(8180))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<UiConfiguration> for HttpConfiguration {
|
|
||||||
fn from(conf: UiConfiguration) -> Self {
|
|
||||||
HttpConfiguration {
|
|
||||||
enabled: conf.enabled,
|
|
||||||
interface: conf.interface,
|
|
||||||
port: conf.port,
|
|
||||||
apis: rpc_apis::ApiSet::UnsafeContext,
|
|
||||||
cors: Some(vec![]),
|
|
||||||
hosts: conf.hosts,
|
|
||||||
server_threads: 1,
|
|
||||||
processing_threads: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for UiConfiguration {
|
|
||||||
fn default() -> Self {
|
|
||||||
UiConfiguration {
|
|
||||||
enabled: cfg!(feature = "ui-enabled"),
|
|
||||||
port: 8180,
|
|
||||||
interface: "127.0.0.1".into(),
|
|
||||||
hosts: Some(vec![]),
|
|
||||||
info_page_only: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct IpcConfiguration {
|
pub struct IpcConfiguration {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
@ -153,7 +101,6 @@ pub struct WsConfiguration {
|
|||||||
pub hosts: Option<Vec<String>>,
|
pub hosts: Option<Vec<String>>,
|
||||||
pub signer_path: PathBuf,
|
pub signer_path: PathBuf,
|
||||||
pub support_token_api: bool,
|
pub support_token_api: bool,
|
||||||
pub ui_address: Option<rpc::Host>,
|
|
||||||
pub dapps_address: Option<rpc::Host>,
|
pub dapps_address: Option<rpc::Host>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +117,6 @@ impl Default for WsConfiguration {
|
|||||||
hosts: Some(Vec::new()),
|
hosts: Some(Vec::new()),
|
||||||
signer_path: replace_home(&data_dir, "$BASE/signer").into(),
|
signer_path: replace_home(&data_dir, "$BASE/signer").into(),
|
||||||
support_token_api: true,
|
support_token_api: true,
|
||||||
ui_address: Some("127.0.0.1:8180".into()),
|
|
||||||
dapps_address: Some("127.0.0.1:8545".into()),
|
dapps_address: Some("127.0.0.1:8545".into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,9 +171,8 @@ pub fn new_ws<D: rpc_apis::Dependencies>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let remote = deps.remote.clone();
|
let remote = deps.remote.clone();
|
||||||
let ui_address = conf.ui_address.clone();
|
let allowed_origins = into_domains(with_domain(conf.origins, domain, &conf.dapps_address));
|
||||||
let allowed_origins = into_domains(with_domain(conf.origins, domain, &ui_address, &conf.dapps_address));
|
let allowed_hosts = into_domains(with_domain(conf.hosts, domain, &Some(url.clone().into())));
|
||||||
let allowed_hosts = into_domains(with_domain(conf.hosts, domain, &Some(url.clone().into()), &None));
|
|
||||||
|
|
||||||
let signer_path;
|
let signer_path;
|
||||||
let path = match conf.support_token_api {
|
let path = match conf.support_token_api {
|
||||||
@ -276,7 +221,7 @@ pub fn new_http<D: rpc_apis::Dependencies>(
|
|||||||
let remote = deps.remote.clone();
|
let remote = deps.remote.clone();
|
||||||
|
|
||||||
let cors_domains = into_domains(conf.cors);
|
let cors_domains = into_domains(conf.cors);
|
||||||
let allowed_hosts = into_domains(with_domain(conf.hosts, domain, &Some(url.clone().into()), &None));
|
let allowed_hosts = into_domains(with_domain(conf.hosts, domain, &Some(url.clone().into())));
|
||||||
|
|
||||||
let start_result = rpc::start_http(
|
let start_result = rpc::start_http(
|
||||||
&addr,
|
&addr,
|
||||||
@ -328,7 +273,7 @@ fn into_domains<T: From<String>>(items: Option<Vec<String>>) -> DomainsValidatio
|
|||||||
items.map(|vals| vals.into_iter().map(T::from).collect()).into()
|
items.map(|vals| vals.into_iter().map(T::from).collect()).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_domain(items: Option<Vec<String>>, domain: &str, ui_address: &Option<rpc::Host>, dapps_address: &Option<rpc::Host>) -> Option<Vec<String>> {
|
fn with_domain(items: Option<Vec<String>>, domain: &str, dapps_address: &Option<rpc::Host>) -> Option<Vec<String>> {
|
||||||
fn extract_port(s: &str) -> Option<u16> {
|
fn extract_port(s: &str) -> Option<u16> {
|
||||||
s.split(':').nth(1).and_then(|s| s.parse().ok())
|
s.split(':').nth(1).and_then(|s| s.parse().ok())
|
||||||
}
|
}
|
||||||
@ -347,7 +292,6 @@ fn with_domain(items: Option<Vec<String>>, domain: &str, ui_address: &Option<rpc
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
add_hosts(ui_address);
|
|
||||||
add_hosts(dapps_address);
|
add_hosts(dapps_address);
|
||||||
}
|
}
|
||||||
items.into_iter().collect()
|
items.into_iter().collect()
|
||||||
|
@ -112,13 +112,11 @@ pub struct RunCmd {
|
|||||||
pub net_settings: NetworkSettings,
|
pub net_settings: NetworkSettings,
|
||||||
pub dapps_conf: dapps::Configuration,
|
pub dapps_conf: dapps::Configuration,
|
||||||
pub ipfs_conf: ipfs::Configuration,
|
pub ipfs_conf: ipfs::Configuration,
|
||||||
pub ui_conf: rpc::UiConfiguration,
|
|
||||||
pub secretstore_conf: secretstore::Configuration,
|
pub secretstore_conf: secretstore::Configuration,
|
||||||
pub private_provider_conf: ProviderConfig,
|
pub private_provider_conf: ProviderConfig,
|
||||||
pub private_encryptor_conf: EncryptorConfig,
|
pub private_encryptor_conf: EncryptorConfig,
|
||||||
pub private_tx_enabled: bool,
|
pub private_tx_enabled: bool,
|
||||||
pub dapp: Option<String>,
|
pub dapp: Option<String>,
|
||||||
pub ui: bool,
|
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub custom_bootnodes: bool,
|
pub custom_bootnodes: bool,
|
||||||
pub stratum: Option<stratum::Options>,
|
pub stratum: Option<stratum::Options>,
|
||||||
@ -185,7 +183,7 @@ fn execute_light_impl(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<Runnin
|
|||||||
execute_upgrades(&cmd.dirs.base, &db_dirs, algorithm, &cmd.compaction)?;
|
execute_upgrades(&cmd.dirs.base, &db_dirs, algorithm, &cmd.compaction)?;
|
||||||
|
|
||||||
// create dirs used by parity
|
// create dirs used by parity
|
||||||
cmd.dirs.create_dirs(cmd.dapps_conf.enabled, cmd.ui_conf.enabled, cmd.secretstore_conf.enabled)?;
|
cmd.dirs.create_dirs(cmd.dapps_conf.enabled, cmd.acc_conf.unlocked_accounts.len() == 0, cmd.secretstore_conf.enabled)?;
|
||||||
|
|
||||||
//print out running parity environment
|
//print out running parity environment
|
||||||
print_running_environment(&spec.name, &cmd.dirs, &db_dirs, &cmd.dapps_conf);
|
print_running_environment(&spec.name, &cmd.dirs, &db_dirs, &cmd.dapps_conf);
|
||||||
@ -323,13 +321,10 @@ fn execute_light_impl(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<Runnin
|
|||||||
fetch: fetch.clone(),
|
fetch: fetch.clone(),
|
||||||
pool: cpu_pool.clone(),
|
pool: cpu_pool.clone(),
|
||||||
signer: signer_service.clone(),
|
signer: signer_service.clone(),
|
||||||
ui_address: cmd.ui_conf.redirection_address(),
|
|
||||||
info_page_only: cmd.ui_conf.info_page_only,
|
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let dapps_middleware = dapps::new(cmd.dapps_conf.clone(), dapps_deps.clone())?;
|
let dapps_middleware = dapps::new(cmd.dapps_conf.clone(), dapps_deps.clone())?;
|
||||||
let ui_middleware = dapps::new_ui(cmd.ui_conf.enabled, dapps_deps)?;
|
|
||||||
|
|
||||||
// start RPCs
|
// start RPCs
|
||||||
let dapps_service = dapps::service(&dapps_middleware);
|
let dapps_service = dapps::service(&dapps_middleware);
|
||||||
@ -373,7 +368,6 @@ fn execute_light_impl(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<Runnin
|
|||||||
let ws_server = rpc::new_ws(cmd.ws_conf, &dependencies)?;
|
let ws_server = rpc::new_ws(cmd.ws_conf, &dependencies)?;
|
||||||
let http_server = rpc::new_http("HTTP JSON-RPC", "jsonrpc", cmd.http_conf.clone(), &dependencies, dapps_middleware)?;
|
let http_server = rpc::new_http("HTTP JSON-RPC", "jsonrpc", cmd.http_conf.clone(), &dependencies, dapps_middleware)?;
|
||||||
let ipc_server = rpc::new_ipc(cmd.ipc_conf, &dependencies)?;
|
let ipc_server = rpc::new_ipc(cmd.ipc_conf, &dependencies)?;
|
||||||
let ui_server = rpc::new_http("Parity Wallet (UI)", "ui", cmd.ui_conf.clone().into(), &dependencies, ui_middleware)?;
|
|
||||||
|
|
||||||
// the informant
|
// the informant
|
||||||
let informant = Arc::new(Informant::new(
|
let informant = Arc::new(Informant::new(
|
||||||
@ -394,7 +388,7 @@ fn execute_light_impl(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<Runnin
|
|||||||
rpc: rpc_direct,
|
rpc: rpc_direct,
|
||||||
informant,
|
informant,
|
||||||
client,
|
client,
|
||||||
keep_alive: Box::new((event_loop, service, ws_server, http_server, ipc_server, ui_server)),
|
keep_alive: Box::new((event_loop, service, ws_server, http_server, ipc_server)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -444,7 +438,7 @@ fn execute_impl<Cr, Rr>(cmd: RunCmd, logger: Arc<RotatingLogger>, on_client_rq:
|
|||||||
execute_upgrades(&cmd.dirs.base, &db_dirs, algorithm, &cmd.compaction)?;
|
execute_upgrades(&cmd.dirs.base, &db_dirs, algorithm, &cmd.compaction)?;
|
||||||
|
|
||||||
// create dirs used by parity
|
// create dirs used by parity
|
||||||
cmd.dirs.create_dirs(cmd.dapps_conf.enabled, cmd.ui_conf.enabled, cmd.secretstore_conf.enabled)?;
|
cmd.dirs.create_dirs(cmd.dapps_conf.enabled, cmd.acc_conf.unlocked_accounts.len() == 0, cmd.secretstore_conf.enabled)?;
|
||||||
|
|
||||||
// run in daemon mode
|
// run in daemon mode
|
||||||
if let Some(pid_file) = cmd.daemon {
|
if let Some(pid_file) = cmd.daemon {
|
||||||
@ -756,12 +750,9 @@ fn execute_impl<Cr, Rr>(cmd: RunCmd, logger: Arc<RotatingLogger>, on_client_rq:
|
|||||||
fetch: fetch.clone(),
|
fetch: fetch.clone(),
|
||||||
pool: cpu_pool.clone(),
|
pool: cpu_pool.clone(),
|
||||||
signer: signer_service.clone(),
|
signer: signer_service.clone(),
|
||||||
ui_address: cmd.ui_conf.redirection_address(),
|
|
||||||
info_page_only: cmd.ui_conf.info_page_only,
|
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
let dapps_middleware = dapps::new(cmd.dapps_conf.clone(), dapps_deps.clone())?;
|
let dapps_middleware = dapps::new(cmd.dapps_conf.clone(), dapps_deps.clone())?;
|
||||||
let ui_middleware = dapps::new_ui(cmd.ui_conf.enabled, dapps_deps)?;
|
|
||||||
|
|
||||||
let dapps_service = dapps::service(&dapps_middleware);
|
let dapps_service = dapps::service(&dapps_middleware);
|
||||||
let deps_for_rpc_apis = Arc::new(rpc_apis::FullDependencies {
|
let deps_for_rpc_apis = Arc::new(rpc_apis::FullDependencies {
|
||||||
@ -807,8 +798,6 @@ fn execute_impl<Cr, Rr>(cmd: RunCmd, logger: Arc<RotatingLogger>, on_client_rq:
|
|||||||
let ws_server = rpc::new_ws(cmd.ws_conf.clone(), &dependencies)?;
|
let ws_server = rpc::new_ws(cmd.ws_conf.clone(), &dependencies)?;
|
||||||
let ipc_server = rpc::new_ipc(cmd.ipc_conf, &dependencies)?;
|
let ipc_server = rpc::new_ipc(cmd.ipc_conf, &dependencies)?;
|
||||||
let http_server = rpc::new_http("HTTP JSON-RPC", "jsonrpc", cmd.http_conf.clone(), &dependencies, dapps_middleware)?;
|
let http_server = rpc::new_http("HTTP JSON-RPC", "jsonrpc", cmd.http_conf.clone(), &dependencies, dapps_middleware)?;
|
||||||
// the ui server
|
|
||||||
let ui_server = rpc::new_http("UI WALLET", "ui", cmd.ui_conf.clone().into(), &dependencies, ui_middleware)?;
|
|
||||||
|
|
||||||
// secret store key server
|
// secret store key server
|
||||||
let secretstore_deps = secretstore::Dependencies {
|
let secretstore_deps = secretstore::Dependencies {
|
||||||
@ -881,7 +870,7 @@ fn execute_impl<Cr, Rr>(cmd: RunCmd, logger: Arc<RotatingLogger>, on_client_rq:
|
|||||||
informant,
|
informant,
|
||||||
client,
|
client,
|
||||||
client_service: Arc::new(service),
|
client_service: Arc::new(service),
|
||||||
keep_alive: Box::new((watcher, updater, ws_server, http_server, ipc_server, ui_server, secretstore_key_server, ipfs_server, event_loop)),
|
keep_alive: Box::new((watcher, updater, ws_server, http_server, ipc_server, secretstore_key_server, ipfs_server, event_loop)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ pub const CODES_FILENAME: &'static str = "authcodes";
|
|||||||
|
|
||||||
pub struct NewToken {
|
pub struct NewToken {
|
||||||
pub token: String,
|
pub token: String,
|
||||||
pub url: String,
|
|
||||||
pub message: String,
|
pub message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,22 +48,19 @@ pub fn codes_path(path: &Path) -> PathBuf {
|
|||||||
p
|
p
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(ws_conf: rpc::WsConfiguration, ui_conf: rpc::UiConfiguration, logger_config: LogConfig) -> Result<String, String> {
|
pub fn execute(ws_conf: rpc::WsConfiguration, logger_config: LogConfig) -> Result<String, String> {
|
||||||
Ok(generate_token_and_url(&ws_conf, &ui_conf, &logger_config)?.message)
|
Ok(generate_token_and_url(&ws_conf, &logger_config)?.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_token_and_url(ws_conf: &rpc::WsConfiguration, ui_conf: &rpc::UiConfiguration, logger_config: &LogConfig) -> Result<NewToken, String> {
|
pub fn generate_token_and_url(ws_conf: &rpc::WsConfiguration, logger_config: &LogConfig) -> Result<NewToken, String> {
|
||||||
let code = generate_new_token(&ws_conf.signer_path, logger_config.color).map_err(|err| format!("Error generating token: {:?}", err))?;
|
let code = generate_new_token(&ws_conf.signer_path, logger_config.color).map_err(|err| format!("Error generating token: {:?}", err))?;
|
||||||
let auth_url = format!("http://{}:{}/#/auth?token={}", ui_conf.interface, ui_conf.port, code);
|
|
||||||
let colored = |s: String| match logger_config.color {
|
let colored = |s: String| match logger_config.color {
|
||||||
true => format!("{}", White.bold().paint(s)),
|
true => format!("{}", White.bold().paint(s)),
|
||||||
false => s,
|
false => s,
|
||||||
};
|
};
|
||||||
|
|
||||||
if !ui_conf.enabled {
|
Ok(NewToken {
|
||||||
return Ok(NewToken {
|
|
||||||
token: code.clone(),
|
token: code.clone(),
|
||||||
url: auth_url.clone(),
|
|
||||||
message: format!(
|
message: format!(
|
||||||
r#"
|
r#"
|
||||||
Generated token:
|
Generated token:
|
||||||
@ -75,22 +71,6 @@ Generated token:
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// And print in to the console
|
|
||||||
Ok(NewToken {
|
|
||||||
token: code.clone(),
|
|
||||||
url: auth_url.clone(),
|
|
||||||
message: format!(
|
|
||||||
r#"
|
|
||||||
Open: {}
|
|
||||||
to authorize your browser.
|
|
||||||
Or use the generated token:
|
|
||||||
{}"#,
|
|
||||||
colored(auth_url),
|
|
||||||
code
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_new_token(path: &Path, logger_config_color: bool) -> io::Result<String> {
|
fn generate_new_token(path: &Path, logger_config_color: bool) -> io::Result<String> {
|
||||||
let path = codes_path(path);
|
let path = codes_path(path);
|
||||||
let mut codes = parity_rpc::AuthCodes::from_file(&path)?;
|
let mut codes = parity_rpc::AuthCodes::from_file(&path)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user