diff --git a/.idea/dictionaries/bt.xml b/.idea/dictionaries/bt.xml index 4bc384823d..a4f9e376ff 100644 --- a/.idea/dictionaries/bt.xml +++ b/.idea/dictionaries/bt.xml @@ -20,6 +20,7 @@ fakeyou ffprobe ghibli + gottagofast greenlight greenlighting greenlit diff --git a/crates/lib/actix_cors_configs/src/configs/gottagofast.rs b/crates/lib/actix_cors_configs/src/configs/gottagofast.rs index ee0437073d..b83348ff21 100644 --- a/crates/lib/actix_cors_configs/src/configs/gottagofast.rs +++ b/crates/lib/actix_cors_configs/src/configs/gottagofast.rs @@ -1,7 +1,67 @@ use actix_cors::Cors; +use log::warn; +use url::{Host, Url}; pub fn add_gotta_go_fast_test_branches(cors: Cors, _is_production: bool) -> Cors { cors.allowed_origin("http://localhost:5173") .allowed_origin("https://pipeline-gottagofast.netlify.app") .allowed_origin("https://test--pipeline-gottagofast.netlify.app") + // Allow Netlify domains within "gottagofast" project. + .allowed_origin_fn(|origin, _req_head| { + let maybe_url = origin.to_str() + .map(|origin| Url::parse(origin)); + + let url = match maybe_url { + Ok(Ok(url)) => url, + _ => { + warn!("Invalid origin: {:?}", origin); + return false + }, + }; + + match url.host() { + Some(Host::Domain(domain)) => { + let is_netlify_domain = domain == "pipeline-gottagofast.netlify.app"; + let is_netlify_branch_deploy = domain.ends_with("--pipeline-gottagofast.netlify.app"); + + is_netlify_domain || is_netlify_branch_deploy + }, + _ => false, + } + }) +} + +// + +#[cfg(test)] +mod tests { + use reusable_types::server_environment::ServerEnvironment; + + use crate::cors::build_cors_config; + use crate::testing::assert_origin_invalid; + use crate::testing::assert_origin_ok; + + #[actix_rt::test] + async fn gotta_go_fast_main() { + let production_cors = build_cors_config(ServerEnvironment::Production); + assert_origin_ok(&production_cors, "https://pipeline-gottagofast.netlify.app").await; + } + + #[actix_rt::test] + async fn gotta_go_fast_branch_deploy() { + let production_cors = build_cors_config(ServerEnvironment::Production); + assert_origin_ok(&production_cors, "https://test--pipeline-gottagofast.netlify.app").await; + } + + #[actix_rt::test] + async fn gotta_go_fast_deploy_preview() { + let production_cors = build_cors_config(ServerEnvironment::Production); + assert_origin_ok(&production_cors, "https://deploy-preview-86--pipeline-gottagofast.netlify.app").await; + } + + #[actix_rt::test] + async fn invalid_netlify_preview_deploy() { + let production_cors = build_cors_config(ServerEnvironment::Production); + assert_origin_invalid(&production_cors, "https://deploy-preview-86--unrelated-project.netlify.app").await; + } } diff --git a/crates/lib/actix_cors_configs/src/cors.rs b/crates/lib/actix_cors_configs/src/cors.rs index 7e190232b2..b66f314a27 100644 --- a/crates/lib/actix_cors_configs/src/cors.rs +++ b/crates/lib/actix_cors_configs/src/cors.rs @@ -2,8 +2,8 @@ use actix_cors::Cors; use log::info; use reusable_types::server_environment::ServerEnvironment; -use crate::configs::development_only::add_development_only; +use crate::configs::development_only::add_development_only; use crate::configs::fakeyou::{add_fakeyou, add_fakeyou_dev_proxy}; use crate::configs::gottagofast::add_gotta_go_fast_test_branches; use crate::configs::legacy::{add_legacy_storyteller_stream, add_legacy_trumped, add_legacy_vocodes, add_power_stream}; @@ -62,44 +62,13 @@ fn do_build_cors_config(is_production: bool) -> Cors { #[cfg(test)] mod tests { - use actix_cors::Cors; - use actix_http::body::{BoxBody, EitherBody}; - use actix_web::dev::{ServiceResponse, Transform}; - use actix_web::http::StatusCode; - use actix_web::test; - use actix_web::test::TestRequest; - use speculoos::asserting; - use reusable_types::server_environment::ServerEnvironment; + use crate::testing::assert_origin_invalid; + use crate::testing::assert_origin_ok; + use super::build_cors_config; - async fn make_test_request(cors: &Cors, hostname: &str) -> ServiceResponse> { - let cors= cors.new_transform(test::ok_service()) - .await - .unwrap(); - - let request = TestRequest::default() - .insert_header(("Origin", hostname)) - .to_srv_request(); - - test::call_service(&cors, request).await - } - - async fn assert_origin_ok(cors: &Cors, hostname: &str) { - let response = make_test_request(cors, hostname).await; - asserting(&format!("Hostname {} is valid", hostname)) - .that(&response.status()) - .is_equal_to(StatusCode::OK); - } - - async fn assert_origin_invalid(cors: &Cors, hostname: &str) { - let response = make_test_request(cors, hostname).await; - asserting(&format!("Hostname {} is invalid", hostname)) - .that(&response.status()) - .is_equal_to(StatusCode::BAD_REQUEST); - } - #[actix_rt::test] async fn test_fakeyou_production() { let production_cors = build_cors_config(ServerEnvironment::Production); diff --git a/crates/lib/actix_cors_configs/src/lib.rs b/crates/lib/actix_cors_configs/src/lib.rs index 538767a1b5..1cecab1089 100644 --- a/crates/lib/actix_cors_configs/src/lib.rs +++ b/crates/lib/actix_cors_configs/src/lib.rs @@ -22,3 +22,6 @@ pub mod cors; pub (crate) mod configs; + +#[cfg(test)] +pub (crate) mod testing; diff --git a/crates/lib/actix_cors_configs/src/testing.rs b/crates/lib/actix_cors_configs/src/testing.rs new file mode 100644 index 0000000000..473b92f0a5 --- /dev/null +++ b/crates/lib/actix_cors_configs/src/testing.rs @@ -0,0 +1,33 @@ +use actix_cors::Cors; +use actix_http::body::{BoxBody, EitherBody}; +use actix_http::StatusCode; +use actix_web::dev::{ServiceResponse, Transform}; +use actix_web::test; +use actix_web::test::TestRequest; +use speculoos::asserting; + +pub (crate) async fn assert_origin_ok(cors: &Cors, hostname: &str) { + let response = make_test_request(cors, hostname).await; + asserting(&format!("Hostname {} is valid", hostname)) + .that(&response.status()) + .is_equal_to(StatusCode::OK); +} + +pub (crate) async fn assert_origin_invalid(cors: &Cors, hostname: &str) { + let response = make_test_request(cors, hostname).await; + asserting(&format!("Hostname {} is invalid", hostname)) + .that(&response.status()) + .is_equal_to(StatusCode::BAD_REQUEST); +} + +async fn make_test_request(cors: &Cors, hostname: &str) -> ServiceResponse> { + let cors= cors.new_transform(test::ok_service()) + .await + .unwrap(); + + let request = TestRequest::default() + .insert_header(("Origin", hostname)) + .to_srv_request(); + + test::call_service(&cors, request).await +}