From d372ac3a41cd617fb64dd9e6ea251065c2bc3d0d Mon Sep 17 00:00:00 2001 From: kasisnu <5044120+kasisnu@users.noreply.github.com> Date: Fri, 8 Dec 2023 16:31:28 +0530 Subject: [PATCH] make billing an optional dependency for local dev --- Cargo.lock | 1 - .../plugins/billing/src/default_routes.rs | 81 ++++---- crates/service/web/storyteller_web/Cargo.toml | 10 +- .../internal_product_to_stripe_lookup_impl.rs | 4 + .../internal_session_cache_purge_impl.rs | 2 + ...ternal_subscription_product_lookup_impl.rs | 3 + .../stripe_internal_user_lookup_impl.rs | 2 + .../service/web/storyteller_web/src/main.rs | 180 +++++++++++------- .../service/web/storyteller_web/src/routes.rs | 12 +- .../web/storyteller_web/src/server_state.rs | 9 +- crates/vendor/limitation/Cargo.toml | 1 - 11 files changed, 184 insertions(+), 121 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1aaf8d3a68..aa2bc9fa15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5994,7 +5994,6 @@ dependencies = [ "actix-web", "actix_helpers", "anyhow", - "async-stripe", "async-trait", "base64 0.21.5", "bcrypt", diff --git a/crates/service/plugins/billing/src/default_routes.rs b/crates/service/plugins/billing/src/default_routes.rs index 48879d2b9d..5d5c52f76f 100644 --- a/crates/service/plugins/billing/src/default_routes.rs +++ b/crates/service/plugins/billing/src/default_routes.rs @@ -1,60 +1,49 @@ //! These routes are recommended, but do not have to be used by consumers of the billing system. use actix_web::{App, HttpResponse, web}; -use actix_web::body::MessageBody; -use actix_web::dev::{ServiceFactory, ServiceRequest, ServiceResponse}; -use actix_web::error::Error; + use crate::stripe::http_endpoints::checkout::create::stripe_create_checkout_session_json_handler::stripe_create_checkout_session_json_handler; use crate::stripe::http_endpoints::checkout::create::stripe_create_checkout_session_redirect_handler::stripe_create_checkout_session_redirect_handler; use crate::stripe::http_endpoints::customer_portal::stripe_create_customer_portal_session_json_handler::stripe_create_customer_portal_session_json_handler; use crate::stripe::http_endpoints::customer_portal::stripe_create_customer_portal_session_redirect_handler::stripe_create_customer_portal_session_redirect_handler; use crate::stripe::http_endpoints::webhook::stripe_webhook_handler::stripe_webhook_handler; +use actix_web::body::MessageBody; +use actix_web::dev::{ServiceFactory, ServiceRequest, ServiceResponse}; +use actix_web::error::Error; +use log::warn; + use crate::users::http_endpoints::list_active_user_subscriptions_handler::list_active_user_subscriptions_handler; -pub fn add_suggested_stripe_billing_routes (app: App) -> App - where - B: MessageBody, - T: ServiceFactory< - ServiceRequest, - Config = (), - Response = ServiceResponse, - Error = Error, - InitError = (), - >, +pub fn add_suggested_stripe_billing_routes(app: App) -> App +where + B: MessageBody, + T: ServiceFactory, Error = Error, InitError = ()>, { - app.service(web::scope("/v1") - .service(web::scope("/billing") - .service(web::resource("/active_subscriptions") - .route(web::get().to(list_active_user_subscriptions_handler)) - .route(web::head().to(|| HttpResponse::Ok())) - ) - ) - .service(web::scope("/stripe") - .service(web::resource("/webhook") - .route(web::post().to(stripe_webhook_handler)) - .route(web::head().to(|| HttpResponse::Ok())) - ) - .service(web::scope("/checkout") - .service(web::resource("/create_redirect") - .route(web::post().to(stripe_create_checkout_session_json_handler)) - .route(web::head().to(|| HttpResponse::Ok())) - ) - .service(web::resource("/redirect") - .route(web::get().to(stripe_create_checkout_session_redirect_handler)) - .route(web::head().to(|| HttpResponse::Ok())) - ) - ) - .service(web::scope("/portal") - .service(web::resource("/create_redirect") - .route(web::post().to(stripe_create_customer_portal_session_json_handler)) - .route(web::head().to(|| HttpResponse::Ok())) - ) - .service(web::resource("/redirect") - .route(web::get().to(stripe_create_customer_portal_session_redirect_handler)) - .route(web::head().to(|| HttpResponse::Ok())) - ) - ) - ) + warn!("Adding suggested Stripe billing routes to app."); + app.service( + web::scope("/v1") + .service(web::scope("/billing") + .service(web::resource("/active_subscriptions") + .route(web::get().to(list_active_user_subscriptions_handler)) + .route(web::head().to(|| HttpResponse::Ok())))) + .service(web::scope("/stripe") + .service(web::resource("/webhook") + .route(web::post().to(stripe_webhook_handler)) + .route(web::head().to(|| HttpResponse::Ok()))) + .service(web::scope("/checkout") + .service(web::resource("/create_redirect") + .route(web::post().to(stripe_create_checkout_session_json_handler)) + .route(web::head().to(|| HttpResponse::Ok()))) + .service(web::resource("/redirect") + .route(web::get().to(stripe_create_checkout_session_redirect_handler)) + .route(web::head().to(|| HttpResponse::Ok())))) + .service(web::scope("/portal") + .service(web::resource("/create_redirect") + .route(web::post().to(stripe_create_customer_portal_session_json_handler)) + .route(web::head().to(|| HttpResponse::Ok()))) + .service(web::resource("/redirect") + .route(web::get().to(stripe_create_customer_portal_session_redirect_handler)) + .route(web::head().to(|| HttpResponse::Ok()))))), ) } diff --git a/crates/service/web/storyteller_web/Cargo.toml b/crates/service/web/storyteller_web/Cargo.toml index 3825873690..713273bd08 100644 --- a/crates/service/web/storyteller_web/Cargo.toml +++ b/crates/service/web/storyteller_web/Cargo.toml @@ -51,7 +51,7 @@ url_config = { path = "../../../lib/url_config" } user_input_common = { path = "../../../lib/user_input_common" } # Internal Components -billing_component = { path = "../../plugins/billing" } +billing_component = { path = "../../plugins/billing", optional = true } users_component = { path = "../../plugins/users" } # Workspace hack (faster compile times) @@ -139,7 +139,7 @@ jwt = "0.13.0" hyper = { version = "0.14.24" } # Money -async-stripe = { version = "0.25.2", default-features = false, features = ["runtime-tokio-hyper-rustls-webpki", "connect", "billing", "checkout", "webhook-events"] } +#async-stripe = { version = "0.25.2", default-features = false, features = ["runtime-tokio-hyper-rustls-webpki", "connect", "billing", "checkout", "webhook-events"] } # Crypto bcrypt = "0.8" # password hashes @@ -172,3 +172,9 @@ diesel = { version = "2.1.3", features = ["mysql"] } [dev-dependencies] speculoos = "0.9.0" # Fluent assertions + + +[features] +default = ["billing", "dep:billing_component"] +billing = ["dep:billing_component"] +all_except_billing = [] \ No newline at end of file diff --git a/crates/service/web/storyteller_web/src/billing/internal_product_to_stripe_lookup_impl.rs b/crates/service/web/storyteller_web/src/billing/internal_product_to_stripe_lookup_impl.rs index 66ed785f56..d01a31ecbc 100644 --- a/crates/service/web/storyteller_web/src/billing/internal_product_to_stripe_lookup_impl.rs +++ b/crates/service/web/storyteller_web/src/billing/internal_product_to_stripe_lookup_impl.rs @@ -1,3 +1,5 @@ + +#[cfg(feature = "billing")] use billing_component::stripe::traits::internal_product_to_stripe_lookup::{InternalProductToStripeLookup, StripeProduct, StripeProductLookupError}; use reusable_types::server_environment::ServerEnvironment; @@ -7,6 +9,8 @@ use crate::configs::plans::plan_list::{DEVELOPMENT_PREMIUM_PLANS_BY_SLUG, PRODUC #[derive(Clone, Copy)] pub struct InternalProductToStripeLookupImpl; + +#[cfg(feature = "billing")] impl InternalProductToStripeLookup for InternalProductToStripeLookupImpl { fn lookup_stripe_product_from_internal_product_key(&self, server_environment: ServerEnvironment, internal_product_key: &str) -> Result, StripeProductLookupError> { let plans_by_slug = match server_environment { diff --git a/crates/service/web/storyteller_web/src/billing/internal_session_cache_purge_impl.rs b/crates/service/web/storyteller_web/src/billing/internal_session_cache_purge_impl.rs index c296ed5296..12623c7519 100644 --- a/crates/service/web/storyteller_web/src/billing/internal_session_cache_purge_impl.rs +++ b/crates/service/web/storyteller_web/src/billing/internal_session_cache_purge_impl.rs @@ -1,5 +1,6 @@ use actix_web::HttpRequest; +#[cfg(feature = "billing")] use billing_component::stripe::traits::internal_session_cache_purge::InternalSessionCachePurge; use redis_caching::redis_ttl_cache::RedisTtlCache; use redis_common::redis_cache_keys::RedisCacheKeys; @@ -19,6 +20,7 @@ impl InternalSessionCachePurgeImpl { } } +#[cfg(feature = "billing")] impl InternalSessionCachePurge for InternalSessionCachePurgeImpl { fn best_effort_purge_session_cache(&self, http_request: &HttpRequest) { // TODO: Clear Redis cache of sessions diff --git a/crates/service/web/storyteller_web/src/billing/stripe_internal_subscription_product_lookup_impl.rs b/crates/service/web/storyteller_web/src/billing/stripe_internal_subscription_product_lookup_impl.rs index 73e17f6307..ac75c1b176 100644 --- a/crates/service/web/storyteller_web/src/billing/stripe_internal_subscription_product_lookup_impl.rs +++ b/crates/service/web/storyteller_web/src/billing/stripe_internal_subscription_product_lookup_impl.rs @@ -1,3 +1,5 @@ + +#[cfg(feature = "billing")] use billing_component::stripe::traits::internal_subscription_product_lookup::{InternalProductLookupError, InternalSubscriptionProduct, InternalSubscriptionProductLookup}; use crate::configs::plans::plan_list::{PLANS_BY_STRIPE_PRICE_ID, PLANS_BY_STRIPE_PRODUCT_ID}; @@ -8,6 +10,7 @@ const SUBSCRIPTION_CATEGORY : &str = "fakeyou"; #[derive(Clone, Copy)] pub struct StripeInternalSubscriptionProductLookupImpl; +#[cfg(feature = "billing")] impl InternalSubscriptionProductLookup for StripeInternalSubscriptionProductLookupImpl { fn lookup_internal_product_from_stripe_product_id(&self, stripe_product_id: &str) -> Result, InternalProductLookupError> { Ok(PLANS_BY_STRIPE_PRODUCT_ID.get(stripe_product_id) diff --git a/crates/service/web/storyteller_web/src/billing/stripe_internal_user_lookup_impl.rs b/crates/service/web/storyteller_web/src/billing/stripe_internal_user_lookup_impl.rs index 71eaeaa108..f55a2bf979 100644 --- a/crates/service/web/storyteller_web/src/billing/stripe_internal_user_lookup_impl.rs +++ b/crates/service/web/storyteller_web/src/billing/stripe_internal_user_lookup_impl.rs @@ -3,6 +3,7 @@ use async_trait::async_trait; use chrono::Utc; use log::warn; +#[cfg(feature = "billing")] use billing_component::stripe::traits::internal_user_lookup::{InternalUserLookup, InternalUserLookupError, SubscriptionKey, UserMetadata}; use users_component::utils::session_checker::SessionChecker; @@ -25,6 +26,7 @@ impl StripeInternalUserLookupImpl { } // NB: Marking async_trait as not needing Sync/Send. Hopefully this doesn't blow up on us. +#[cfg(feature = "billing")] #[async_trait(?Send)] impl InternalUserLookup for StripeInternalUserLookupImpl { async fn lookup_user_from_http_request(&self, http_request: &HttpRequest) -> Result, InternalUserLookupError> { diff --git a/crates/service/web/storyteller_web/src/main.rs b/crates/service/web/storyteller_web/src/main.rs index e77ed85093..5bfba0bf4e 100644 --- a/crates/service/web/storyteller_web/src/main.rs +++ b/crates/service/web/storyteller_web/src/main.rs @@ -46,11 +46,6 @@ use actix_helpers::middleware::disabled_endpoint_filter::disabled_endpoint_filte use actix_helpers::middleware::disabled_endpoint_filter::disabled_endpoints::disabled_endpoints::DisabledEndpoints; use actix_helpers::middleware::disabled_endpoint_filter::disabled_endpoints::exact_match_disabled_endpoints::ExactMatchDisabledEndpoints; use actix_helpers::middleware::disabled_endpoint_filter::disabled_endpoints::prefix_disabled_endpoints::PrefixDisabledEndpoints; -use billing_component::stripe::stripe_config::{FullUrlOrPath, StripeCheckoutConfigs, StripeConfig, StripeCustomerPortalConfigs, StripeSecrets}; -use billing_component::stripe::traits::internal_product_to_stripe_lookup::InternalProductToStripeLookup; -use billing_component::stripe::traits::internal_session_cache_purge::InternalSessionCachePurge; -use billing_component::stripe::traits::internal_subscription_product_lookup::InternalSubscriptionProductLookup; -use billing_component::stripe::traits::internal_user_lookup::InternalUserLookup; use bootstrap::bootstrap::{bootstrap, BootstrapArgs}; use cloud_storage::bucket_client::BucketClient; use config::common_env::CommonEnv; @@ -71,10 +66,19 @@ use users_component::cookies::anonymous_visitor_tracking::avt_cookie_manager::Av use users_component::cookies::session::session_cookie_manager::SessionCookieManager; use users_component::utils::session_checker::SessionChecker; -use crate::billing::internal_product_to_stripe_lookup_impl::InternalProductToStripeLookupImpl; -use crate::billing::internal_session_cache_purge_impl::InternalSessionCachePurgeImpl; -use crate::billing::stripe_internal_subscription_product_lookup_impl::StripeInternalSubscriptionProductLookupImpl; -use crate::billing::stripe_internal_user_lookup_impl::StripeInternalUserLookupImpl; +#[cfg(feature = "billing")] +use +{ + crate::billing::internal_product_to_stripe_lookup_impl::InternalProductToStripeLookupImpl, + crate::billing::internal_session_cache_purge_impl::InternalSessionCachePurgeImpl, + crate::billing::stripe_internal_subscription_product_lookup_impl::StripeInternalSubscriptionProductLookupImpl, + crate::billing::stripe_internal_user_lookup_impl::StripeInternalUserLookupImpl, + billing_component::stripe::stripe_config::{FullUrlOrPath, StripeCheckoutConfigs, StripeConfig, StripeCustomerPortalConfigs, StripeSecrets}, + billing_component::stripe::traits::internal_product_to_stripe_lookup::InternalProductToStripeLookup, + billing_component::stripe::traits::internal_session_cache_purge::InternalSessionCachePurge, + billing_component::stripe::traits::internal_subscription_product_lookup::InternalSubscriptionProductLookup, + billing_component::stripe::traits::internal_user_lookup::InternalUserLookup, +}; use crate::configs::static_api_tokens::{StaticApiTokenConfig, StaticApiTokens, StaticApiTokenSet}; use crate::http_server::middleware::pushback_filter_middleware::PushbackFilter; use crate::http_server::web_utils::redis_rate_limiter::RedisRateLimiter; @@ -382,6 +386,7 @@ async fn main() -> AnyhowResult<()> { }); + #[cfg(feature = "billing")] let stripe_configs = StripeConfig { checkout: StripeCheckoutConfigs { success_url: FullUrlOrPath::Path(easyenv::get_env_string_required("STRIPE_CHECKOUT_SUCCESS_URL_PATH")?), @@ -398,6 +403,9 @@ async fn main() -> AnyhowResult<()> { }, }; + #[cfg(not(feature = "billing"))] + let stripe_configs = (); + let server_environment = ServerEnvironment::from_str(&easyenv::get_env_string_required("SERVER_ENVIRONMENT")?) .ok_or(anyhow!("invalid server environment"))?; @@ -424,10 +432,6 @@ async fn main() -> AnyhowResult<()> { let third_party_url_redirector = ThirdPartyUrlRedirector::new(server_environment); - let stripe_client = { - let api_secret = stripe_configs.secrets.secret_key.clone(); - stripe::Client::new(api_secret) - }; // NB: Docker creates this file within container builds. let build_sha = std::fs::read_to_string("/GIT_SHA") @@ -455,7 +459,6 @@ async fn main() -> AnyhowResult<()> { }, stripe: StripeSettings { config: stripe_configs, - client: stripe_client, }, hostname: server_hostname, server_environment, @@ -636,62 +639,105 @@ pub async fn serve(server_state: ServerState) -> AnyhowResult<()> //let log_format = "[%{HOSTNAME}e] %a \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\" %T"; let log_format = "[%{HOSTNAME}e] IP=[%{X-Forwarded-For}i] \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\" %T"; - HttpServer::new(move || { - // NB: Safe to clone due to internal arc - let ip_ban_list = server_state_arc.ip_ban_list.clone(); - let cidr_ban_set= server_state_arc.cidr_ban_set.clone(); + #[cfg(feature = "billing")] + { + let server = HttpServer::new(move || { + // NB: Safe to clone due to internal arc + let ip_ban_list = server_state_arc.ip_ban_list.clone(); + let cidr_ban_set= server_state_arc.cidr_ban_set.clone(); - // NB: Dynamic dispatch needs to be wrapped with Arc. - let product_lookup : Arc = Arc::new(StripeInternalSubscriptionProductLookupImpl {}); - let stripe_lookup : Arc = Arc::new(InternalProductToStripeLookupImpl{}); - let user_lookup : Arc = Arc::new(StripeInternalUserLookupImpl::new( - server_state_arc.session_checker.clone(), - server_state_arc.mysql_pool.clone(), - )); - let session_cache_purge : Arc = Arc::new(InternalSessionCachePurgeImpl::new( - server_state_arc.session_checker.clone(), - server_state_arc.redis_ttl_cache.clone(), - )); + // NB: Dynamic dispatch needs to be wrapped with Arc. + let product_lookup : Arc = Arc::new(StripeInternalSubscriptionProductLookupImpl {}); + let stripe_lookup : Arc = Arc::new(InternalProductToStripeLookupImpl{}); + let user_lookup : Arc = Arc::new(StripeInternalUserLookupImpl::new( + server_state_arc.session_checker.clone(), + server_state_arc.mysql_pool.clone(), + )); + let session_cache_purge : Arc = Arc::new(InternalSessionCachePurgeImpl::new( + server_state_arc.session_checker.clone(), + server_state_arc.redis_ttl_cache.clone(), + )); - // NB: app_data being clone()'d below should all be safe (dependencies included) - let app = App::new() - .app_data(web::Data::new(server_state_arc.firehose_publisher.clone())) - .app_data(web::Data::new(server_state_arc.mysql_pool.clone())) - .app_data(web::Data::new(server_state_arc.redis_pool.clone())) - .app_data(web::Data::new(server_state_arc.redis_ttl_cache.clone())) - .app_data(web::Data::new(server_state_arc.session_checker.clone())) - .app_data(web::Data::new(server_state_arc.avt_cookie_manager.clone())) - .app_data(web::Data::new(server_state_arc.session_cookie_manager.clone())) - .app_data(web::Data::new(server_state_arc.stripe.clone().config.clone())) - .app_data(web::Data::new(server_state_arc.stripe.clone().client.clone())) - .app_data(web::Data::new(server_state_arc.third_party_url_redirector.clone())) - .app_data(web::Data::new(server_state_arc.email_sender.clone())) - .app_data(web::Data::new(old_server_environment)) - .app_data(web::Data::new(new_server_environment)) - .app_data(web::Data::from(product_lookup)) // NB: Data::from(Arc) for dynamic dispatch - .app_data(web::Data::from(stripe_lookup)) // NB: Data::from(Arc) for dynamic dispatch - .app_data(web::Data::from(user_lookup)) // NB: Data::from(Arc) for dynamic dispatch - .app_data(web::Data::from(session_cache_purge)) // NB: Data::from(Arc) for dynamic dispatch - .app_data(server_state_arc.clone()) - .wrap(build_cors_config(old_server_environment)) - .wrap(DefaultHeaders::new() - .header("X-Backend-Hostname", &hostname) - .header("X-Build-Sha", server_state_arc.server_info.build_sha.clone())) - .wrap(PushbackFilter::new(&server_state_arc.flags.clone())) - .wrap(DisabledEndpointFilter::new(disabled_endpoints.clone())) - .wrap(BannedIpFilter::new(ip_ban_list)) - .wrap(BannedCidrFilter::new(cidr_ban_set)) - .wrap(Logger::new(&log_format) - .exclude("/liveness") - .exclude("/readiness")) - .wrap(middleware::Compress::default()); + // NB: app_data being clone()'d below should all be safe (dependencies included) + let app = App::new() + .app_data(web::Data::new(server_state_arc.firehose_publisher.clone())) + .app_data(web::Data::new(server_state_arc.mysql_pool.clone())) + .app_data(web::Data::new(server_state_arc.redis_pool.clone())) + .app_data(web::Data::new(server_state_arc.redis_ttl_cache.clone())) + .app_data(web::Data::new(server_state_arc.session_checker.clone())) + .app_data(web::Data::new(server_state_arc.avt_cookie_manager.clone())) + .app_data(web::Data::new(server_state_arc.session_cookie_manager.clone())) + .app_data(web::Data::new(server_state_arc.stripe.clone().config.clone())) + .app_data(web::Data::new(server_state_arc.third_party_url_redirector.clone())) + .app_data(web::Data::new(server_state_arc.email_sender.clone())) + .app_data(web::Data::new(old_server_environment)) + .app_data(web::Data::new(new_server_environment)) + .app_data(web::Data::from(product_lookup)) // NB: Data::from(Arc) for dynamic dispatch + .app_data(web::Data::from(stripe_lookup)) // NB: Data::from(Arc) for dynamic dispatch + .app_data(web::Data::from(user_lookup)) // NB: Data::from(Arc) for dynamic dispatch + .app_data(web::Data::from(session_cache_purge)) // NB: Data::from(Arc) for dynamic dispatch + .app_data(server_state_arc.clone()) + .wrap(build_cors_config(old_server_environment)) + .wrap(DefaultHeaders::new() + .header("X-Backend-Hostname", &hostname) + .header("X-Build-Sha", server_state_arc.server_info.build_sha.clone())) + .wrap(PushbackFilter::new(&server_state_arc.flags.clone())) + .wrap(DisabledEndpointFilter::new(disabled_endpoints.clone())) + .wrap(BannedIpFilter::new(ip_ban_list)) + .wrap(BannedCidrFilter::new(cidr_ban_set)) + .wrap(Logger::new(&log_format) + .exclude("/liveness") + .exclude("/readiness")) + .wrap(middleware::Compress::default()); - add_routes(app, old_server_environment) - }) - .bind(bind_address)? - .workers(num_workers) - .run() - .await?; + crate::routes::add_routes(app, old_server_environment) + }); + + server.bind(bind_address)? + .workers(num_workers) + .run() + .await?; + } + #[cfg(not(feature = "billing"))] { + let server = HttpServer::new(move || { + // NB: Safe to clone due to internal arc + let ip_ban_list = server_state_arc.ip_ban_list.clone(); + let cidr_ban_set= server_state_arc.cidr_ban_set.clone(); + + // NB: app_data being clone()'d below should all be safe (dependencies included) + let app = App::new() + .app_data(web::Data::new(server_state_arc.firehose_publisher.clone())) + .app_data(web::Data::new(server_state_arc.mysql_pool.clone())) + .app_data(web::Data::new(server_state_arc.redis_pool.clone())) + .app_data(web::Data::new(server_state_arc.redis_ttl_cache.clone())) + .app_data(web::Data::new(server_state_arc.session_checker.clone())) + .app_data(web::Data::new(server_state_arc.avt_cookie_manager.clone())) + .app_data(web::Data::new(server_state_arc.session_cookie_manager.clone())) + .app_data(web::Data::new(server_state_arc.third_party_url_redirector.clone())) + .app_data(web::Data::new(server_state_arc.email_sender.clone())) + .app_data(web::Data::new(old_server_environment)) + .app_data(web::Data::new(new_server_environment)) + .app_data(server_state_arc.clone()) + .wrap(build_cors_config(old_server_environment)) + .wrap(DefaultHeaders::new() + .header("X-Backend-Hostname", &hostname) + .header("X-Build-Sha", server_state_arc.server_info.build_sha.clone())) + .wrap(PushbackFilter::new(&server_state_arc.flags.clone())) + .wrap(DisabledEndpointFilter::new(disabled_endpoints.clone())) + .wrap(BannedIpFilter::new(ip_ban_list)) + .wrap(BannedCidrFilter::new(cidr_ban_set)) + .wrap(Logger::new(&log_format) + .exclude("/liveness") + .exclude("/readiness")) + .wrap(middleware::Compress::default()); + + add_routes(app, old_server_environment) + }); + server.bind(bind_address)? + .workers(num_workers) + .run() + .await?; + } Ok(()) } diff --git a/crates/service/web/storyteller_web/src/routes.rs b/crates/service/web/storyteller_web/src/routes.rs index eb67880dd5..79c804f5c1 100644 --- a/crates/service/web/storyteller_web/src/routes.rs +++ b/crates/service/web/storyteller_web/src/routes.rs @@ -5,6 +5,7 @@ use actix_web::dev::{ServiceRequest, ServiceResponse}; use actix_web::error::Error; use actix_helpers::route_builder::RouteBuilder; +#[cfg(feature = "billing")] use billing_component::default_routes::add_suggested_stripe_billing_routes; use reusable_types::server_environment::ServerEnvironment; use users_component::default_routes::add_suggested_api_v1_account_creation_and_session_routes; @@ -228,15 +229,20 @@ pub fn add_routes (app: App, server_environment: ServerEnvironment) -> // ==================== Stats ==================== + let mut app = RouteBuilder::from_app(app) .add_get("/v1/stats/queues", get_unified_queue_stats_handler) .into_app(); // ==================== COMPONENTS ==================== - app = add_suggested_api_v1_account_creation_and_session_routes(app); // /create_account, /session, /login, /logout - app = add_suggested_stripe_billing_routes(app); // /stripe, billing, webhooks, etc. - + + #[cfg(feature = "billing")] + let mut app = add_suggested_stripe_billing_routes(app); // /stripe, billing, webhooks, etc. + + #[cfg(not(feature = "billing"))] + let mut app = app; + // ==================== SERVICE ==================== app.service( web::resource("/_status") diff --git a/crates/service/web/storyteller_web/src/server_state.rs b/crates/service/web/storyteller_web/src/server_state.rs index 41ddadf1d3..9c13604162 100644 --- a/crates/service/web/storyteller_web/src/server_state.rs +++ b/crates/service/web/storyteller_web/src/server_state.rs @@ -4,6 +4,7 @@ use sqlx::MySqlPool; use actix_helpers::middleware::banned_cidr_filter::banned_cidr_set::BannedCidrSet; use actix_helpers::middleware::banned_ip_filter::ip_ban_list::ip_ban_list::IpBanList; +#[cfg(feature = "billing")] use billing_component::stripe::stripe_config::StripeConfig; use cloud_storage::bucket_client::BucketClient; use email_sender::smtp_email_sender::SmtpEmailSender; @@ -197,10 +198,16 @@ pub struct EphemeralInMemoryCaches { pub leaderboard: SingleItemTtlCache, } +#[cfg(feature = "billing")] #[derive(Clone)] pub struct StripeSettings { pub config: StripeConfig, - pub client: stripe::Client, +} + +#[cfg(not(feature = "billing"))] +#[derive(Clone)] +pub struct StripeSettings { + pub config: () } /// Flags set at service startup diff --git a/crates/vendor/limitation/Cargo.toml b/crates/vendor/limitation/Cargo.toml index e5b5aa6d77..7c4015b643 100644 --- a/crates/vendor/limitation/Cargo.toml +++ b/crates/vendor/limitation/Cargo.toml @@ -22,7 +22,6 @@ chrono = "0.4.9" futures = "0.1.29" redis = "0.13.0" time = "0.1.42" -my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" } # Workspace hack (faster compile times) my-workspace-hack = { version = "0.1", path = "../../my-workspace-hack" }