From 9acf6331101d6238362559fdb2ae9b0aa9054717 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Sat, 30 Oct 2021 16:02:08 +0100 Subject: [PATCH] frontend_base_uri config value in chartered-web --- Cargo.lock | 1 + chartered-web/Cargo.toml | 1 + chartered-web/src/config.rs | 18 +++++++++++------- chartered-web/src/main.rs | 21 ++++++++++++++++++++- book/src/guide/config-reference.md | 7 +++++++ 5 files changed, 34 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ec64b38..63f9518 100644 --- a/Cargo.lock +++ a/Cargo.lock @@ -562,6 +562,7 @@ "tower-http 0.1.1 (git+https://github.com/tower-rs/tower-http?branch=cors)", "tracing", "tracing-subscriber", + "url", ] [[package]] diff --git a/chartered-web/Cargo.toml b/chartered-web/Cargo.toml index 1f7479f..76acea5 100644 --- a/chartered-web/Cargo.toml +++ a/chartered-web/Cargo.toml @@ -38,3 +38,4 @@ toml = "0.5" tracing = "0.1" tracing-subscriber = "0.2" +url = { version = "2.2", features = ["serde"] } diff --git a/chartered-web/src/config.rs b/chartered-web/src/config.rs index e8e45a5..d15e120 100644 --- a/chartered-web/src/config.rs +++ a/chartered-web/src/config.rs @@ -5,6 +5,7 @@ use std::collections::HashMap; use std::net::SocketAddr; use thiserror::Error; +use url::Url; #[derive(Error, Debug)] pub enum Error { @@ -12,6 +13,8 @@ OpenId(#[from] openid::error::Error), #[error("Failed to create file system handle: {0}")] Fs(#[from] Box), + #[error("Failed to build URL: {0}")] + Parse(#[from] url::ParseError), } pub type OidcClients = HashMap; @@ -22,6 +25,7 @@ pub bind_address: SocketAddr, pub database_uri: String, pub storage_uri: String, + pub frontend_base_uri: Url, pub auth: AuthConfig, #[serde(deserialize_with = "deserialize_encryption_key")] pub encryption_key: ChaCha20Poly1305Key, @@ -41,12 +45,14 @@ .iter() .filter(|(_, config)| config.enabled) .map(|(name, config)| async move { + let redirect = self.frontend_base_uri.join("auth/login/oauth")?; + Ok::<_, Error>(( name.to_string(), DiscoveredClient::discover( config.client_id.to_string(), config.client_secret.to_string(), - Some("http://127.0.0.1:1234/auth/login/oauth".to_string()), + Some(redirect.to_string()), config.discovery_uri.clone(), ) .await?, @@ -75,8 +81,7 @@ #[derive(Deserialize, Debug)] pub struct OAuthConfig { pub enabled: bool, - #[serde(deserialize_with = "deserialize_url")] - pub discovery_uri: reqwest::Url, + pub discovery_uri: Url, pub client_id: String, pub client_secret: String, } @@ -91,11 +96,4 @@ } Ok(ChaCha20Poly1305Key::clone_from_slice(key.as_bytes())) -} - -fn deserialize_url<'de, D: serde::Deserializer<'de>>( - deserializer: D, -) -> Result { - let uri = String::deserialize(deserializer)?; - reqwest::Url::parse(&uri).map_err(D::Error::custom) } diff --git a/chartered-web/src/main.rs b/chartered-web/src/main.rs index 9b35ccf..60d715b 100644 --- a/chartered-web/src/main.rs +++ a/chartered-web/src/main.rs @@ -15,8 +15,9 @@ use std::{fmt::Formatter, path::PathBuf, sync::Arc}; use thiserror::Error; use tower::ServiceBuilder; -use tower_http::cors::{Any, CorsLayer}; +use tower_http::cors::{CorsLayer, Origin}; use tracing::info; +use url::Url; #[derive(Parser)] #[clap(version = clap::crate_version!(), author = clap::crate_authors!())] @@ -85,6 +86,8 @@ .layer_fn(middleware::logging::LoggingMiddleware) .into_inner(); + let config = Arc::new(config); + let app = Router::new() .route("/", get(hello_world)) .nest( @@ -105,7 +108,6 @@ ), ) .layer(middleware_stack) - // TODO!!! .layer( CorsLayer::new() .allow_methods(vec![ @@ -117,7 +119,16 @@ Method::OPTIONS, ]) .allow_headers(vec![header::CONTENT_TYPE, header::USER_AGENT]) - .allow_origin(Any) + .allow_origin(Origin::predicate({ + let config = config.clone(); + move |url, _| { + url.to_str() + .ok() + .and_then(|url| Url::parse(url).ok()) + .map(|url| url.host_str() == config.frontend_base_uri.host_str()) + .unwrap_or_default() + } + })) .allow_credentials(false), ) .layer(AddExtensionLayer::new(pool)) @@ -127,7 +138,7 @@ .layer(AddExtensionLayer::new(Arc::new( config.get_file_system().await?, ))) - .layer(AddExtensionLayer::new(Arc::new(config))); + .layer(AddExtensionLayer::new(config.clone())); info!("HTTP server listening on {}", bind_address); @@ -151,6 +162,8 @@ Database(#[from] chartered_db::Error), #[error("Failed to spawn HTTP server: {0}")] ServerSpawn(Box), + #[error("Failed to build CORS header: {0}")] + Cors(axum::http::header::InvalidHeaderValue), } impl std::fmt::Debug for InitError { diff --git a/book/src/guide/config-reference.md b/book/src/guide/config-reference.md index ee2d088..8998c28 100644 --- a/book/src/guide/config-reference.md +++ a/book/src/guide/config-reference.md @@ -80,6 +80,8 @@ storage_uri = "s3://s3-eu-west-1.amazonaws.com/my-cool-crate-store/" # or file:///var/lib/chartered +frontend_base_uri = "http://localhost:1234/" + [auth.password] enabled = true # enables password auth @@ -111,6 +113,11 @@ A URI in which crates should be stored, this can either be an `s3://` connection URI, or a local file path using `file://`. + +#### `frontend_base_uri` +- Type: `string` + +The base URL at which the frontend is being hosted. #### `[auth.password]` The `[auth.password]` table controls the username/password-based authentication method. -- rgit 0.1.3