From f29c876ad6cf58bc5656134d7071448224074569 Mon Sep 17 00:00:00 2001 From: phoenix Date: Sat, 13 Jun 2026 14:52:11 -0400 Subject: [PATCH] Saving changes --- src/config/mod.rs | 125 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/main.rs | 11 ++++ 3 files changed, 137 insertions(+) create mode 100644 src/config/mod.rs create mode 100644 src/lib.rs diff --git a/src/config/mod.rs b/src/config/mod.rs new file mode 100644 index 0000000..d51b480 --- /dev/null +++ b/src/config/mod.rs @@ -0,0 +1,125 @@ + +pub mod host { + pub const PORT: i64 = 9081; + + pub fn get_full() -> String { + String::new() + } +} + +pub mod init { + use std::time::Duration; + +use axum::routing::{delete, get, patch, post}; +use tower_http::timeout::TimeoutLayer; +use utoipa::OpenApi; + +use crate::callers::coverart as coverart_caller; +use crate::callers::queue::coverart as coverart_queue_callers; +use crate::callers::queue::metadata as metadata_queue_caller; +use crate::callers::queue::song as song_queue_callers; +use crate::callers::song as song_caller; +use coverart_caller::endpoint as coverart_endpoints; +use coverart_caller::response as coverart_responses; +use coverart_queue_callers::endpoint as coverart_queue_endpoints; +use coverart_queue_callers::response as coverart_queue_responses; +use metadata_queue_caller::endpoint as metadata_queue_endpoints; +use metadata_queue_caller::response as metadata_queue_responses; +use song_caller::endpoint as song_endpoints; +use song_caller::response as song_responses; +use song_queue_callers::endpoint as song_queue_endpoints; +use song_queue_callers::response as song_queue_responses; + +mod cors { + pub async fn configure_cors() -> tower_http::cors::CorsLayer { + let cors = tower_http::cors::CorsLayer::new() + .allow_methods([ + axum::http::Method::GET, + axum::http::Method::POST, + axum::http::Method::PUT, + axum::http::Method::DELETE, + ]) // Specify allowed methods:cite[2] + .allow_headers([ + axum::http::header::CONTENT_TYPE, + axum::http::header::AUTHORIZATION, + ]) // Specify allowed headers:cite[2] + .allow_credentials(true) // If you need to send cookies or authentication headers:cite[2] + .max_age(std::time::Duration::from_secs(3600)); // Cache the preflight response for 1 hour:cite[2] + + // Dynamically set the allowed origin based on the environment + match std::env::var(textsender_models::envy::keys::APP_ENV).as_deref() { + Ok("production") => { + // In production, allow only your specific, trusted origins + let allowed_origins_env = textsender_models::envy::environment::get_allowed_origins().await; + match textsender_models::envy::utility::delimitize(&allowed_origins_env) { + Ok(alwd) => { + let allowed_origins: Vec = alwd + .into_iter() + .map(|a| a.parse::().unwrap()) + .collect(); + cors.allow_origin(allowed_origins) + } + Err(err) => { + eprintln!("Error getting allowed origins: Error: {err:?}"); + std::process::exit(-1); + } + } + } + _ => { + // Development (default): Allow localhost origins + cors.allow_origin(vec![ + "http://localhost:8000".parse().unwrap(), + "http://127.0.0.1:8000".parse().unwrap(), + "http://localhost:4200".parse().unwrap(), + "http://127.0.0.1:4200".parse().unwrap(), + ]) + } + } + } +} + +#[derive(utoipa::OpenApi)] +#[openapi( + paths(song_queue_endpoints::queue_song,), + components(schemas(song_queue_callers::response::song_queue::Response)), + tags( + (name = "textsender API", description = "Web API to manage texting") + ) +)] +struct ApiDoc; + +pub async fn routes() -> axum::Router { + axum::Router::new() + .route( + crate::callers::queue::endpoints::QUEUESONG, + post(crate::callers::queue::song::endpoint::queue_song).route_layer( + axum::middleware::from_fn(crate::auth::auth::), + ), + ) + .layer(cors::configure_cors().await) +} + +pub async fn app() -> axum::Router { + let pool = crate::db::create_pool() + .await + .expect("Failed to create pool"); + + crate::db::migrations(&pool).await; + + let cors = cors::configure_cors().await; + + routes() + .await + .merge( + utoipa_swagger_ui::SwaggerUi::new("/swagger-ui") + .url("/api-docs/openapi.json", ApiDoc::openapi()), + ) + .layer(axum::Extension(pool)) + .layer(axum::extract::DefaultBodyLimit::max(1024 * 1024 * 1024)) + .layer(TimeoutLayer::with_status_code( + axum::http::StatusCode::OK, + Duration::from_secs(300), + )) + .layer(cors) +} +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..ef68c36 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +pub mod config; diff --git a/src/main.rs b/src/main.rs index 47a4039..d499e1d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,4 +2,15 @@ async fn main() { // initialize tracing tracing_subscriber::fmt::init(); + + match tokio::net::TcpListener::bind(textsender_api::config::host::get_full()).await { + Ok(listener) => { + // build our application with routes + let app = textsender_api::config::init::app().await; + axum::serve(listener, app).await.unwrap(); + } + Err(err) => { + eprintln!("Error: {err:?}") + } + } }