CORS separation by environments + tests

This commit is contained in:
Brandon Thomas committed 2022-12-04 02:40:28 -05:00
1 parent fa108a5303
commit a15324adee
18 files changed
+360 -151

No files matched your search

Generated
+54 -51
View File
@@ -8,7 +8,7 @@ version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3720d0064a0ce5c0de7bd93bdb0a6caebab2a9b5668746145d7b3b0c5da02914"
dependencies = [
"actix-rt 2.4.0",
"actix-rt 2.7.0",
"actix_derive",
"bitflags",
"bytes 1.0.1",
@@ -22,7 +22,7 @@ dependencies = [
"parking_lot 0.11.1",
"pin-project-lite 0.2.6",
"smallvec 1.6.1",
"tokio 1.13.0",
"tokio 1.16.1",
"tokio-util 0.6.9",
]
@@ -55,7 +55,7 @@ dependencies = [
"log",
"memchr",
"pin-project-lite 0.2.6",
"tokio 1.13.0",
"tokio 1.16.1",
"tokio-util 0.6.9",
]
@@ -181,7 +181,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9b510d35f13987537289f38bf136e7e702a5c87cc28760310cc459544f40afd"
dependencies = [
"actix-codec 0.4.1",
"actix-rt 2.4.0",
"actix-rt 2.7.0",
"actix-service 2.0.1",
"actix-tls 3.0.0-beta.7",
"actix-utils 3.0.0",
@@ -212,7 +212,7 @@ dependencies = [
"rand 0.8.4",
"sha-1",
"smallvec 1.6.1",
"tokio 1.13.0",
"tokio 1.16.1",
"zstd",
]
@@ -299,13 +299,13 @@ dependencies = [
[[package]]
name = "actix-rt"
version = "2.4.0"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a0c218d0a17c120f10ee0c69c9f0c45d87319e8f66b1f065e8412b612fc3e24"
checksum = "7ea16c295198e958ef31930a6ef37d0fb64e9ca3b6116e6b93a8bdae96ee1000"
dependencies = [
"actix-macros 0.2.3",
"futures-core",
"tokio 1.13.0",
"tokio 1.16.1",
]
[[package]]
@@ -334,14 +334,14 @@ version = "2.0.0-beta.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7367665785765b066ad16e1086d26a087f696bc7c42b6f93004ced6cfcf1eeca"
dependencies = [
"actix-rt 2.4.0",
"actix-rt 2.7.0",
"actix-service 2.0.1",
"actix-utils 3.0.0",
"futures-core",
"log",
"mio 0.7.11",
"num_cpus",
"tokio 1.13.0",
"tokio 1.16.1",
]
[[package]]
@@ -413,7 +413,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4af84e13e4600829858a3e68079be710d1ada461431e1e4c5ae663479ea0a3c"
dependencies = [
"actix-codec 0.4.1",
"actix-rt 2.4.0",
"actix-rt 2.7.0",
"actix-service 2.0.1",
"actix-utils 3.0.0",
"derive_more",
@@ -502,7 +502,7 @@ dependencies = [
"actix-http 3.0.0-beta.11",
"actix-macros 0.2.3",
"actix-router 0.5.0-beta.2",
"actix-rt 2.4.0",
"actix-rt 2.7.0",
"actix-server 2.0.0-beta.6",
"actix-service 2.0.1",
"actix-utils 3.0.0",
@@ -547,7 +547,7 @@ dependencies = [
"bytestring",
"futures-core",
"pin-project 1.0.7",
"tokio 1.13.0",
"tokio 1.16.1",
]
[[package]]
@@ -710,7 +710,7 @@ dependencies = [
"smart-default",
"smol_str",
"thiserror",
"tokio 1.13.0",
"tokio 1.16.1",
"uuid",
]
@@ -877,7 +877,7 @@ dependencies = [
"serde_derive",
"serde_json",
"sqlx",
"tokio 1.13.0",
"tokio 1.16.1",
"toml",
"url_config",
]
@@ -1147,7 +1147,7 @@ dependencies = [
"futures-core",
"memchr",
"pin-project-lite 0.2.6",
"tokio 1.13.0",
"tokio 1.16.1",
"tokio-util 0.6.9",
]
@@ -1639,7 +1639,7 @@ dependencies = [
"subprocess",
"subprocess_common",
"tempdir",
"tokio 1.13.0",
"tokio 1.16.1",
"tts_common",
]
@@ -2032,7 +2032,7 @@ dependencies = [
"http",
"indexmap",
"slab",
"tokio 1.13.0",
"tokio 1.16.1",
"tokio-util 0.6.9",
"tracing",
]
@@ -2189,6 +2189,7 @@ version = "0.0.1"
dependencies = [
"actix-cors 0.6.0-beta.3",
"actix-http 3.0.0-beta.11",
"actix-rt 2.7.0",
"actix-web 4.0.0-beta.10",
"anyhow",
"base64 0.13.0",
@@ -2199,9 +2200,11 @@ dependencies = [
"log",
"once_cell",
"regex",
"reusable_types",
"serde",
"serde_derive",
"serde_json",
"speculoos",
"toml",
]
@@ -2274,7 +2277,7 @@ dependencies = [
"itoa 0.4.7",
"pin-project-lite 0.2.6",
"socket2 0.4.0",
"tokio 1.13.0",
"tokio 1.16.1",
"tower-service",
"tracing",
"want",
@@ -2289,7 +2292,7 @@ dependencies = [
"bytes 1.0.1",
"hyper 0.14.14",
"native-tls",
"tokio 1.13.0",
"tokio 1.16.1",
"tokio-native-tls",
]
@@ -2334,7 +2337,7 @@ dependencies = [
"actix-files",
"actix-http 3.0.0-beta.11",
"actix-multipart",
"actix-rt 2.4.0",
"actix-rt 2.7.0",
"actix-service 2.0.1",
"actix-utils 3.0.0",
"actix-web 4.0.0-beta.10",
@@ -2393,7 +2396,7 @@ dependencies = [
"subprocess",
"tempdir",
"time 0.2.26",
"tokio 1.13.0",
"tokio 1.16.1",
"toml",
"tts_common",
"twitch_common",
@@ -2453,7 +2456,7 @@ dependencies = [
"storage_buckets_common",
"subprocess",
"tempdir",
"tokio 1.13.0",
"tokio 1.16.1",
"tts_common",
]
@@ -2996,7 +2999,7 @@ dependencies = [
"rand 0.7.3",
"serde",
"serde_json",
"tokio 1.13.0",
"tokio 1.16.1",
"uuid",
]
@@ -3664,7 +3667,7 @@ dependencies = [
"percent-encoding 2.2.0",
"pin-project-lite 0.2.6",
"sha1",
"tokio 1.13.0",
"tokio 1.16.1",
"tokio-util 0.6.9",
"url 2.3.1",
]
@@ -3758,7 +3761,7 @@ dependencies = [
"serde",
"serde_json",
"serde_urlencoded",
"tokio 1.13.0",
"tokio 1.16.1",
"tokio-native-tls",
"url 2.3.1",
"wasm-bindgen",
@@ -3886,7 +3889,7 @@ dependencies = [
"sha2 0.10.5",
"thiserror",
"time 0.3.14",
"tokio 1.13.0",
"tokio 1.16.1",
"tokio-stream",
"url 2.3.1",
]
@@ -3941,7 +3944,7 @@ dependencies = [
"pin-project-lite 0.2.6",
"rxml_validation",
"smartstring",
"tokio 1.13.0",
"tokio 1.16.1",
]
[[package]]
@@ -4378,10 +4381,10 @@ version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d1bd069de53442e7a320f525a6d4deb8bb0621ac7a55f7eccbc2b58b57f43d0"
dependencies = [
"actix-rt 2.4.0",
"actix-rt 2.7.0",
"native-tls",
"once_cell",
"tokio 1.13.0",
"tokio 1.16.1",
"tokio-native-tls",
]
@@ -4457,7 +4460,7 @@ dependencies = [
"container_common",
"log",
"rust-s3",
"tokio 1.13.0",
"tokio 1.16.1",
]
[[package]]
@@ -4468,7 +4471,7 @@ dependencies = [
"actix-files",
"actix-http 3.0.0-beta.11",
"actix-multipart",
"actix-rt 2.4.0",
"actix-rt 2.7.0",
"actix-service 2.0.1",
"actix-utils 3.0.0",
"actix-web 4.0.0-beta.10",
@@ -4532,7 +4535,7 @@ dependencies = [
"subprocess",
"tempdir",
"time 0.2.26",
"tokio 1.13.0",
"tokio 1.16.1",
"toml",
"tts_common",
"twitch_api2",
@@ -4813,11 +4816,10 @@ dependencies = [
[[package]]
name = "tokio"
version = "1.13.0"
version = "1.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "588b2d10a336da58d877567cd8fb8a14b463e2104910f8132cd054b4b96e29ee"
checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a"
dependencies = [
"autocfg 1.0.1",
"bytes 1.0.1",
"libc",
"memchr",
@@ -4865,9 +4867,9 @@ dependencies = [
[[package]]
name = "tokio-macros"
version = "1.5.1"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "114383b041aa6212c579467afa0075fbbdd0718de036100bc0ba7961d8cb9095"
checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
dependencies = [
"proc-macro2",
"quote",
@@ -4881,7 +4883,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
dependencies = [
"native-tls",
"tokio 1.13.0",
"tokio 1.16.1",
]
[[package]]
@@ -4910,7 +4912,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6"
dependencies = [
"rustls",
"tokio 1.13.0",
"tokio 1.16.1",
"webpki",
]
@@ -4922,7 +4924,7 @@ checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3"
dependencies = [
"futures-core",
"pin-project-lite 0.2.6",
"tokio 1.13.0",
"tokio 1.16.1",
]
[[package]]
@@ -4959,7 +4961,7 @@ dependencies = [
"log",
"pin-project 1.0.7",
"rustls",
"tokio 1.13.0",
"tokio 1.16.1",
"tokio-rustls",
"tungstenite",
"webpki",
@@ -5009,7 +5011,7 @@ dependencies = [
"futures-sink",
"log",
"pin-project-lite 0.2.6",
"tokio 1.13.0",
"tokio 1.16.1",
]
[[package]]
@@ -5130,7 +5132,7 @@ dependencies = [
"storage_buckets_common",
"subprocess",
"tempdir",
"tokio 1.13.0",
"tokio 1.16.1",
"tts_common",
]
@@ -5161,7 +5163,7 @@ dependencies = [
"storage_buckets_common",
"subprocess",
"tempdir",
"tokio 1.13.0",
"tokio 1.16.1",
"tts_common",
]
@@ -5211,7 +5213,7 @@ dependencies = [
"actix-cors 0.5.4",
"actix-files",
"actix-http 3.0.0-beta.11",
"actix-rt 2.4.0",
"actix-rt 2.7.0",
"actix-service 2.0.1",
"actix-utils 3.0.0",
"actix-web 4.0.0-beta.10",
@@ -5259,7 +5261,7 @@ dependencies = [
"sha2 0.9.5",
"sqlx",
"time 0.2.26",
"tokio 1.13.0",
"tokio 1.16.1",
"tokio-tungstenite",
"toml",
"tts_common",
@@ -5464,6 +5466,7 @@ dependencies = [
"actix-web 4.0.0-beta.10",
"anyhow",
"http_server_common",
"reusable_types",
]
[[package]]
@@ -5576,7 +5579,7 @@ dependencies = [
"storage_buckets_common",
"subprocess",
"tempdir",
"tokio 1.13.0",
"tokio 1.16.1",
"tts_common",
]
@@ -5607,7 +5610,7 @@ dependencies = [
"storage_buckets_common",
"subprocess",
"tempdir",
"tokio 1.13.0",
"tokio 1.16.1",
"tts_common",
]
@@ -5742,7 +5745,7 @@ dependencies = [
"actix-cors 0.5.4",
"actix-files",
"actix-http 3.0.0-beta.11",
"actix-rt 2.4.0",
"actix-rt 2.7.0",
"actix-service 2.0.1",
"actix-utils 3.0.0",
"actix-web 4.0.0-beta.10",
@@ -5791,7 +5794,7 @@ dependencies = [
"sha2 0.9.5",
"sqlx",
"time 0.2.26",
"tokio 1.13.0",
"tokio 1.16.1",
"tokio-tungstenite",
"toml",
"twitch_api2",
+5
View File
@@ -16,6 +16,7 @@ path = "src/lib.rs"
# Internal
container_common = { path = "../container_common" }
reusable_types = { path = "../reusable_types" }
# External
anyhow = "1.0.40"
@@ -40,3 +41,7 @@ serde = "1.0.125"
serde_derive = "1.0.125"
serde_json = "1.0.64"
toml = "0.5.8"
[dev-dependencies]
actix-rt = "2.7.0"
speculoos = "0.9.0" # Fluent assertions
+262 -79
View File
@@ -1,10 +1,174 @@
use actix_cors::Cors;
use actix_http::http;
use log::info;
use reusable_types::server_environment::ServerEnvironment;
// TODO: Take an environment.
/// Return cors config for FakeYou / Vocodes / OBS / local development
pub fn build_common_cors_config() -> Cors {
Cors::default()
pub fn build_cors_config(server_environment: ServerEnvironment) -> Cors {
let is_production = server_environment.is_deployed_in_production();
info!("Building CORS for environment: {:?}", server_environment);
do_build_cors_config(is_production)
}
/// Return cors config for FakeYou / Vocodes / OBS / local development
pub fn build_production_cors_config() -> Cors {
const IS_PRODUCTION : bool = true;
do_build_cors_config(IS_PRODUCTION)
}
fn do_build_cors_config(is_production: bool) -> Cors {
let mut cors = Cors::default();
info!("Building CORS for production: {}", is_production);
cors = add_fakeyou(cors, is_production);
cors = add_storyteller(cors, is_production);
cors = add_power_stream(cors, is_production);
cors = add_legacy_storyteller_stream(cors, is_production);
cors = add_legacy_vocodes(cors, is_production);
cors = add_legacy_trumped(cors, is_production);
if !is_production {
cors = add_development_only(cors);
}
// Remaining setup
cors.allowed_methods(vec!["GET", "POST", "OPTIONS", "DELETE"])
.supports_credentials()
.allowed_headers(vec![
http::header::ACCEPT,
http::header::ACCESS_CONTROL_ALLOW_ORIGIN, // Tabulator Ajax
http::header::CONTENT_TYPE,
http::header::ACCESS_CONTROL_ALLOW_CREDENTIALS, // https://stackoverflow.com/a/46412839
http::header::HeaderName::from_static("x-requested-with") // Tabulator Ajax sends
])
.max_age(3600)
}
pub fn add_fakeyou(cors: Cors, is_production: bool) -> Cors {
// TODO: Remove non-SSL "http://" from production in safe rollout
if is_production {
cors
// FakeYou (Production)
.allowed_origin("http://api.fakeyou.com")
.allowed_origin("http://fakeyou.com")
.allowed_origin("https://api.fakeyou.com")
.allowed_origin("https://fakeyou.com")
// FakeYou (Staging)
.allowed_origin("http://staging.fakeyou.com")
.allowed_origin("https://staging.fakeyou.com")
} else {
cors
// FakeYou (Development)
.allowed_origin("http://dev.fakeyou.com")
.allowed_origin("http://development.fakeyou.com")
.allowed_origin("https://dev.fakeyou.com")
.allowed_origin("https://development.fakeyou.com")
}
}
pub fn add_power_stream(cors: Cors, is_production: bool) -> Cors {
// TODO: Remove non-SSL "http://" from production in safe rollout
if is_production {
cors
.allowed_origin("https://dash.power.stream")
.allowed_origin("https://power.stream")
} else {
cors
.allowed_origin("http://dev.dash.power.stream")
.allowed_origin("http://dev.power.stream")
.allowed_origin("https://dev.dash.power.stream")
.allowed_origin("https://dev.power.stream")
}
}
pub fn add_storyteller(cors: Cors, is_production: bool) -> Cors {
// TODO: Remove non-SSL "http://" from production in safe rollout
if is_production {
cors
// Storyteller.io (Production)
.allowed_origin("http://api.storyteller.io")
.allowed_origin("http://storyteller.io")
.allowed_origin("https://api.storyteller.io")
.allowed_origin("https://storyteller.io")
// Storyteller.io (Staging)
.allowed_origin("http://staging.storyteller.io")
.allowed_origin("https://staging.storyteller.io")
// Storyteller.io (Development Proxy)
.allowed_origin("http://development-proxy.storyteller.io")
.allowed_origin("https://development-proxy.storyteller.io")
} else {
cors
// Storyteller.io (Development)
.allowed_origin("http://dev.storyteller.io")
.allowed_origin("https://dev.storyteller.io")
}
}
pub fn add_legacy_storyteller_stream(cors: Cors, is_production: bool) -> Cors {
// TODO: Remove non-SSL "http://" from production in safe rollout
if is_production {
cors
// Storyteller.stream (Production)
.allowed_origin("http://api.storyteller.stream")
.allowed_origin("http://obs.storyteller.stream")
.allowed_origin("http://storyteller.stream")
.allowed_origin("http://ws.storyteller.stream")
.allowed_origin("https://api.storyteller.stream")
.allowed_origin("https://obs.storyteller.stream")
.allowed_origin("https://storyteller.stream")
.allowed_origin("https://ws.storyteller.stream")
// Storyteller.stream (Staging)
.allowed_origin("http://staging.obs.storyteller.stream")
.allowed_origin("http://staging.storyteller.stream")
.allowed_origin("https://staging.obs.storyteller.stream")
.allowed_origin("https://staging.storyteller.stream")
// Legacy "create.storyteller.io" (Production)
.allowed_origin("http://create.storyteller.io")
.allowed_origin("http://obs.storyteller.io")
.allowed_origin("http://ws.storyteller.io")
.allowed_origin("https://create.storyteller.io")
.allowed_origin("https://obs.storyteller.io")
.allowed_origin("https://ws.storyteller.io")
} else {
cors // NB: None!
}
}
pub fn add_legacy_vocodes(cors: Cors, is_production: bool) -> Cors {
if is_production {
cors
// Vocodes (Production)
.allowed_origin("https://api.vo.codes")
.allowed_origin("https://vo.codes")
.allowed_origin("https://vocodes.com")
} else {
cors
// Vocodes (Development)
.allowed_origin("http://dev.api.vo.codes")
.allowed_origin("http://dev.vo.codes")
.allowed_origin("https://dev.api.vo.codes")
.allowed_origin("https://dev.vo.codes")
}
}
pub fn add_legacy_trumped(cors: Cors, is_production: bool) -> Cors {
if is_production {
cors
// Trumped (Production)
.allowed_origin("https://trumped.com")
} else {
cors
// Trumped (Development)
.allowed_origin("http://dev.trumped.com")
.allowed_origin("https://dev.trumped.com")
}
}
pub fn add_development_only(cors: Cors) -> Cors {
cors
// Local Development (Localhost)
.allowed_origin("http://localhost:12345")
.allowed_origin("http://localhost:3000")
@@ -33,79 +197,98 @@ pub fn build_common_cors_config() -> Cors {
.allowed_origin("https://jungle.horse")
.allowed_origin("https://obs.jungle.horse")
.allowed_origin("https://ws.jungle.horse")
// FakeYou
.allowed_origin("http://api.fakeyou.com")
.allowed_origin("http://fakeyou.com")
.allowed_origin("https://api.fakeyou.com")
.allowed_origin("https://fakeyou.com")
// FakeYou (Staging)
.allowed_origin("http://staging.fakeyou.com")
.allowed_origin("https://staging.fakeyou.com")
// FakeYou (Development)
.allowed_origin("http://development.fakeyou.com")
.allowed_origin("https://development.fakeyou.com")
.allowed_origin("http://dev.fakeyou.com")
.allowed_origin("https://dev.fakeyou.com")
// FakeYou (Development Proxy)
.allowed_origin("http://development-proxy.fakeyou.com")
.allowed_origin("https://development-proxy.fakeyou.com")
// Storyteller.io
.allowed_origin("http://api.storyteller.io")
.allowed_origin("http://create.storyteller.io")
.allowed_origin("http://obs.storyteller.io")
.allowed_origin("http://storyteller.io")
.allowed_origin("http://ws.storyteller.io")
.allowed_origin("https://api.storyteller.io")
.allowed_origin("https://create.storyteller.io")
.allowed_origin("https://obs.storyteller.io")
.allowed_origin("https://storyteller.io")
.allowed_origin("https://ws.storyteller.io")
// Storyteller.io (Staging)
.allowed_origin("http://staging.storyteller.io")
.allowed_origin("https://staging.storyteller.io")
// Storyteller.io (Development)
.allowed_origin("http://development.storyteller.io")
.allowed_origin("https://development.storyteller.io")
.allowed_origin("http://dev.storyteller.io")
.allowed_origin("https://dev.storyteller.io")
// Storyteller.io (Development Proxy)
.allowed_origin("http://development-proxy.storyteller.io")
.allowed_origin("https://development-proxy.storyteller.io")
// Storyteller.stream
.allowed_origin("http://api.storyteller.stream")
.allowed_origin("http://obs.storyteller.stream")
.allowed_origin("http://storyteller.stream")
.allowed_origin("http://ws.storyteller.stream")
.allowed_origin("https://api.storyteller.stream")
.allowed_origin("https://obs.storyteller.stream")
.allowed_origin("https://storyteller.stream")
.allowed_origin("https://ws.storyteller.stream")
// Storyteller.stream (Staging)
.allowed_origin("http://staging.obs.storyteller.stream")
.allowed_origin("http://staging.storyteller.stream")
.allowed_origin("https://staging.obs.storyteller.stream")
.allowed_origin("https://staging.storyteller.stream")
// Trumped (legacy)
.allowed_origin("http://trumped.com")
.allowed_origin("https://trumped.com")
// Vocodes (legacy)
.allowed_origin("http://api.vo.codes")
.allowed_origin("http://mumble.stream")
.allowed_origin("http://vo.codes")
.allowed_origin("http://vocodes.com")
.allowed_origin("https://api.vo.codes")
.allowed_origin("https://mumble.stream")
.allowed_origin("https://vo.codes")
.allowed_origin("https://vocodes.com")
// Remaining setup
.allowed_methods(vec!["GET", "POST", "OPTIONS", "DELETE"])
.supports_credentials()
.allowed_headers(vec![
http::header::ACCEPT,
http::header::ACCESS_CONTROL_ALLOW_ORIGIN, // Tabulator Ajax
http::header::CONTENT_TYPE,
http::header::ACCESS_CONTROL_ALLOW_CREDENTIALS, // https://stackoverflow.com/a/46412839
http::header::HeaderName::from_static("x-requested-with") // Tabulator Ajax sends
])
.max_age(3600)
}
}
#[cfg(test)]
mod tests {
use actix_cors::Cors;
use actix_web::dev::{Service, ServiceRequest, ServiceResponse, Transform};
use actix_web::http::StatusCode;
use actix_web::test::TestRequest;
use actix_web::{Error, test};
use crate::cors::build_cors_config;
use reusable_types::server_environment::ServerEnvironment;
use speculoos::{assert_that, asserting};
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);
// Valid Origin
assert_origin_ok(&production_cors, "https://fakeyou.com").await;
assert_origin_ok(&production_cors, "https://api.fakeyou.com").await;
assert_origin_ok(&production_cors, "https://staging.fakeyou.com").await;
// Invalid Origin
assert_origin_invalid(&production_cors, "https://fake.fakeyou.com").await;
assert_origin_invalid(&production_cors, "https://jungle.horse").await;
assert_origin_invalid(&production_cors, "http://localhost:54321").await;
}
#[actix_rt::test]
async fn test_fakeyou_development() {
let development_cors = build_cors_config(ServerEnvironment::Development);
// Valid Origin
assert_origin_ok(&development_cors, "https://dev.fakeyou.com").await;
assert_origin_ok(&development_cors, "http://localhost:54321").await;
// Invalid Origin
assert_origin_invalid(&development_cors, "https://fakeyou.com").await;
assert_origin_invalid(&development_cors, "https://api.fakeyou.com").await;
assert_origin_invalid(&development_cors, "https://staging.fakeyou.com").await;
}
#[actix_rt::test]
async fn test_storyteller_production() {
let production_cors = build_cors_config(ServerEnvironment::Production);
// Valid Origin
assert_origin_ok(&production_cors, "https://storyteller.io").await;
assert_origin_ok(&production_cors, "https://api.storyteller.io").await;
assert_origin_ok(&production_cors, "https://staging.storyteller.io").await;
// Invalid Origin
assert_origin_invalid(&production_cors, "https://dev.storyteller.io").await;
assert_origin_invalid(&production_cors, "http://dev.storyteller.io").await;
}
#[actix_rt::test]
async fn test_storyteller_development() {
let development_cors = build_cors_config(ServerEnvironment::Development);
// Valid Origin
assert_origin_ok(&development_cors, "https://dev.storyteller.io").await;
assert_origin_ok(&development_cors, "http://localhost:54321").await;
// Invalid Origin
assert_origin_invalid(&development_cors, "https://storyteller.io").await;
assert_origin_invalid(&development_cors, "https://staging.storyteller.io").await;
}
}
+2 -1
View File
@@ -19,4 +19,5 @@ pub mod generic_download_type;
pub mod stripe;
pub mod vocoder_type;
#[cfg(test)] pub mod test_helpers;
#[cfg(test)] pub mod test_helpers;
pub mod server_environment;
@@ -17,9 +17,20 @@ impl ServerEnvironment {
match environment {
"dev" | "DEV" | "development" | "DEVELOPMENT" => Some(ServerEnvironment::Development),
"prod" | "PROD" | "production" | "PRODUCTION" => Some(ServerEnvironment::Production),
// "stage" | "STAGE" | "staging" | "STAGING" => Some(ServerEnvironment::Staging),
_ => None,
}
}
/// Reports whether the software is running in production.
/// This is useful once proper "staging" backends gets introduced, as currently staging frontend
/// is served by the production backend.
pub fn is_deployed_in_production(&self) -> bool {
match self {
ServerEnvironment::Development => false,
ServerEnvironment::Production => true,
}
}
}
#[cfg(test)]
@@ -49,4 +60,10 @@ mod tests {
assert_eq!(ServerEnvironment::from_str("pRoDs"), None);
assert_eq!(ServerEnvironment::from_str("staging"), None);
}
#[test]
fn test_is_deployed_in_production() {
assert_eq!(true, ServerEnvironment::Production.is_deployed_in_production());
assert_eq!(false, ServerEnvironment::Development.is_deployed_in_production());
}
}
+1
View File
@@ -16,6 +16,7 @@ path = "src/lib.rs"
# Internal
http_server_common = { path = "../../lib/http_server_common" }
reusable_types = { path = "../../lib/reusable_types" }
# External
actix-web = "4.0.0-beta.10"
-1
View File
@@ -51,5 +51,4 @@ Here are the domain names we handle:
#![allow(dead_code)]
#![allow(non_snake_case)]
pub mod server_environment;
pub mod third_party_url_redirector;
@@ -1,8 +1,8 @@
use actix_web::HttpRequest;
use actix_web::http::Uri;
use anyhow::anyhow;
use crate::server_environment::ServerEnvironment;
use http_server_common::request::get_request_host::get_request_host;
use reusable_types::server_environment::ServerEnvironment;
use std::ops::Deref;
use std::str::FromStr;
@@ -79,7 +79,7 @@ mod tests {
use actix_web::HttpRequest;
use actix_web::http::header::HOST;
use actix_web::test::TestRequest;
use crate::server_environment::ServerEnvironment;
use reusable_types::server_environment::ServerEnvironment;
use crate::third_party_url_redirector::ThirdPartyUrlRedirector;
fn request_with_host(hostname: &str) -> HttpRequest {
@@ -16,7 +16,7 @@ use sqlx::MySqlPool;
use std::collections::HashMap;
use std::fmt;
use stripe::{CheckoutSession, CheckoutSessionMode, CreateCheckoutSession, CreateCheckoutSessionLineItems};
use url_config::server_environment::ServerEnvironment;
use reusable_types::server_environment::ServerEnvironment;
use url_config::third_party_url_redirector::ThirdPartyUrlRedirector;
// =============== Request ===============
@@ -15,7 +15,7 @@ use sqlx::MySqlPool;
use std::collections::HashMap;
use std::fmt;
use stripe::{CheckoutSession, CheckoutSessionMode, CreateCheckoutSession, CreateCheckoutSessionLineItems};
use url_config::server_environment::ServerEnvironment;
use reusable_types::server_environment::ServerEnvironment;
use url_config::third_party_url_redirector::ThirdPartyUrlRedirector;
// =============== Request ===============
@@ -11,7 +11,7 @@ use sqlx::MySqlPool;
use std::collections::HashMap;
use std::str::FromStr;
use stripe::{CheckoutSession, CheckoutSessionMode, CreateCheckoutSession, CreateCheckoutSessionAutomaticTax, CreateCheckoutSessionLineItems, CreateCheckoutSessionPaymentIntentData, CreateCheckoutSessionSubscriptionData, CustomerId, ParseIdError};
use url_config::server_environment::ServerEnvironment;
use reusable_types::server_environment::ServerEnvironment;
use url_config::third_party_url_redirector::ThirdPartyUrlRedirector;
/// Create a checkout session and return the URL
@@ -190,7 +190,7 @@ mod tests {
use crate::stripe::traits::internal_user_lookup::{MockInternalUserLookup, UserMetadata};
use mockall::predicate::*;
use tokio;
use url_config::server_environment::ServerEnvironment;
use reusable_types::server_environment::ServerEnvironment;
use url_config::third_party_url_redirector::ThirdPartyUrlRedirector;
#[tokio::test]
@@ -3,7 +3,7 @@ use mockall::{automock, mock, predicate::*};
use std::error::Error;
use std::fmt::{Display, Formatter};
use url_config::server_environment::ServerEnvironment;
use reusable_types::server_environment::ServerEnvironment;
/// Errors for this component are not strongly typed.
#[derive(Debug)]
@@ -27,7 +27,7 @@ use config::shared_constants::{DEFAULT_MYSQL_CONNECTION_STRING, DEFAULT_RUST_LOG
use container_common::anyhow_result::AnyhowResult;
use crate::routes::add_routes;
use crate::server_state::{EnvConfig, InMemoryCaches, ServerState};
use http_server_common::cors::build_common_cors_config;
use http_server_common::cors::build_production_cors_config;
use limitation::Limiter;
use log::info;
use memory_caching::single_item_ttl_cache::SingleItemTtlCache;
@@ -227,7 +227,7 @@ pub async fn serve(server_state: ServerState) -> AnyhowResult<()>
let app = App::new()
.app_data(server_state_arc.clone())
.wrap(build_common_cors_config())
.wrap(build_production_cors_config())
.wrap(DefaultHeaders::new()
.header("X-Backend-Hostname", &hostname)
.header("X-Build-Sha", build_sha.trim()))
@@ -1,6 +1,6 @@
use billing_component::stripe::traits::internal_product_to_stripe_lookup::{InternalProductToStripeLookup, StripeProduct, StripeProductLookupError};
use crate::configs::plans::plan_list::{ALL_PLANS_BY_SLUG, DEVELOPMENT_PREMIUM_PLANS_BY_SLUG, PRODUCTION_PREMIUM_PLANS_BY_SLUG};
use url_config::server_environment::ServerEnvironment;
use reusable_types::server_environment::ServerEnvironment;
/// A simple Actix injectable action
#[derive(Clone, Copy)]
@@ -1,8 +1,8 @@
use std::ops::Deref;
use chrono::Utc;
use crate::configs::plans::plan::Plan;
use crate::configs::plans::plan_list::{DEVELOPMENT_PREMIUM_PLANS, DEVELOPMENT_PREMIUM_PLANS_BY_SLUG, FREE_LOGGED_IN_PLAN, FREE_LOGGED_OUT_PLAN, LOYALTY_PLANS_BY_SLUG, PRODUCTION_PREMIUM_PLANS, PRODUCTION_PREMIUM_PLANS_BY_SLUG};
use url_config::server_environment::ServerEnvironment;
use reusable_types::server_environment::ServerEnvironment;
use std::ops::Deref;
use users_component::utils::user_session_extended::{UserSessionExtended, UserSessionSubscriptionPlan};
/// Look up the most appropriate plan for the session.
@@ -64,7 +64,7 @@ pub mod tests {
use chrono::{Duration, Utc};
use crate::configs::plans::get_correct_plan_for_session::get_correct_plan_for_session;
use crate::configs::plans::plan_list::{ALL_PLANS_BY_SLUG, FREE_LOGGED_IN_PLAN, FREE_LOGGED_OUT_PLAN};
use url_config::server_environment::ServerEnvironment;
use reusable_types::server_environment::ServerEnvironment;
use users_component::utils::user_session_extended::{UserSessionExtended, UserSessionSubscriptionPlan};
#[test]
+3 -3
View File
@@ -68,13 +68,14 @@ use crate::util::encrypted_sort_id::SortKeyCrypto;
use database_queries::mediators::badge_granter::BadgeGranter;
use database_queries::mediators::firehose_publisher::FirehosePublisher;
use futures::Future;
use http_server_common::cors::build_common_cors_config;
use http_server_common::cors::{build_cors_config, build_production_cors_config};
use limitation::Limiter;
use log::{error, info};
use memory_caching::single_item_ttl_cache::SingleItemTtlCache;
use r2d2_redis::RedisConnectionManager;
use r2d2_redis::r2d2;
use r2d2_redis::redis::Commands;
use reusable_types::server_environment::ServerEnvironment;
use sqlx::MySqlPool;
use sqlx::mysql::MySqlPoolOptions;
use std::sync::Arc;
@@ -82,7 +83,6 @@ use std::time::Duration;
use storage_buckets_common::bucket_client::BucketClient;
use tokio::runtime::Runtime;
use twitch_common::twitch_secrets::TwitchSecrets;
use url_config::server_environment::ServerEnvironment;
use url_config::third_party_url_redirector::ThirdPartyUrlRedirector;
use users_component::utils::session_checker::SessionChecker;
use users_component::utils::session_cookie_manager::SessionCookieManager;
@@ -438,7 +438,7 @@ pub async fn serve(server_state: ServerState) -> AnyhowResult<()>
.app_data(web::Data::from(stripe_lookup)) // NB: Data::from(Arc<T>) for dynamic dispatch
.app_data(web::Data::from(user_lookup)) // NB: Data::from(Arc<T>) for dynamic dispatch
.app_data(server_state_arc.clone())
.wrap(build_common_cors_config())
.wrap(build_cors_config(server_state_arc.server_environment.clone()))
.wrap(DefaultHeaders::new()
.header("X-Backend-Hostname", &hostname)
.header("X-Build-Sha", build_sha.trim()))
@@ -12,9 +12,9 @@ use database_queries::queries::tts::tts_inference_jobs::get_pending_tts_inferenc
use database_queries::queries::w2l::w2l_templates::list_w2l_templates::W2lTemplateRecordForList;
use memory_caching::single_item_ttl_cache::SingleItemTtlCache;
use r2d2_redis::{r2d2, RedisConnectionManager};
use reusable_types::server_environment::ServerEnvironment;
use sqlx::MySqlPool;
use storage_buckets_common::bucket_client::BucketClient;
use url_config::server_environment::ServerEnvironment;
use url_config::third_party_url_redirector::ThirdPartyUrlRedirector;
use users_component::utils::session_checker::SessionChecker;
use users_component::utils::session_cookie_manager::SessionCookieManager;
+2 -2
View File
@@ -28,7 +28,7 @@ use crate::endpoints_ws::obs_gateway_websocket_handler::obs_gateway_websocket_ha
use crate::server_state::{ObsGatewayServerState, EnvConfig, TwitchOauthSecrets, BackendsConfig, MultithreadingConfig};
use futures::Future;
use futures::executor::ThreadPool;
use http_server_common::cors::build_common_cors_config;
use http_server_common::cors::build_production_cors_config;
use http_server_common::endpoints::default_route_404::default_route_404;
use http_server_common::endpoints::root_index::get_root_index;
use limitation::Limiter;
@@ -165,7 +165,7 @@ pub async fn serve(server_state: ObsGatewayServerState) -> AnyhowResult<()>
HttpServer::new(move || {
App::new()
.app_data(server_state_arc.clone())
.wrap(build_common_cors_config())
.wrap(build_production_cors_config())
.wrap(Logger::new(&log_format)
.exclude("/liveness")
.exclude("/readiness"))