Files
schedtxt_api/src/config/mod.rs
T
phoenix 89b347b3f6
schedtxt_api Build / Rustfmt (push) Successful in 40s
schedtxt_api Build / Check (push) Successful in 1m21s
schedtxt_api Build / Test Suite (push) Successful in 2m50s
schedtxt_api Build / Clippy (push) Successful in 2m51s
schedtxt_api Build / build (push) Successful in 3m49s
Dependency name change (#33)
Reviewed-on: #33
2026-07-13 18:06:17 -04:00

220 lines
9.1 KiB
Rust

pub mod host {
pub const PORT: i64 = 9081;
pub fn get_full() -> String {
let address: &str = "0.0.0.0";
format!("{}:{}", address, PORT)
}
}
pub mod init {
use std::time::Duration;
use axum::routing::{delete, get, patch, post};
use tower_http::timeout::TimeoutLayer;
use utoipa::OpenApi;
use crate::caller::contact as contact_caller;
use crate::caller::message as message_caller;
use crate::caller::message::event as event_caller;
use crate::caller::message::scheduling as scheduling_caller;
use contact_caller::endpoint as contact_endpoints;
use contact_caller::response as contact_responses;
use event_caller::endpoint as event_endpoints;
use event_caller::response as event_responses;
use message_caller::endpoint as message_endpoints;
use message_caller::response as message_responses;
use scheduling_caller::endpoint as scheduling_endpoints;
use scheduling_caller::response as scheduling_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::PATCH,
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(schedtxt_models::envy::keys::APP_ENV).as_deref() {
Ok("production") => {
// In production, allow only your specific, trusted origins
let allowed_origins_env =
schedtxt_models::envy::environment::get_allowed_origins();
match schedtxt_models::envy::utility::delimitize(&allowed_origins_env) {
Ok(alwd) => {
let allowed_origins: Vec<axum::http::HeaderValue> = alwd
.into_iter()
.map(|a| a.parse::<axum::http::HeaderValue>().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![
format!("http://localhost:{}", super::super::host::PORT)
.parse()
.unwrap(),
format!("http://127.0.0.1:{}", super::super::host::PORT)
.parse()
.unwrap(),
"http://localhost:4200".parse().unwrap(),
"http://127.0.0.1:4200".parse().unwrap(),
])
}
}
}
}
#[derive(utoipa::OpenApi)]
#[openapi(
paths(contact_endpoints::create_contact,
message_endpoints::create_message,
scheduling_endpoints::schedule_message,
),
components(schemas(contact_responses::AddContactResponse, message_responses::AddMessageResponse,
scheduling_responses::ScheduleMessageResponse,
event_responses::RecordMessageEventResponse
)),
tags(
(name = "schedtxt API", description = "Web API to manage texting")
)
)]
struct ApiDoc;
pub async fn routes() -> axum::Router {
axum::Router::new()
.route(
crate::caller::endpoints::ADD_CONTACT,
post(contact_endpoints::create_contact).route_layer(axum::middleware::from_fn(
crate::auth::auth::<axum::body::Body>,
)),
)
.route(
crate::caller::endpoints::GET_CONTACT,
get(contact_endpoints::get_contacts).route_layer(axum::middleware::from_fn(
crate::auth::auth::<axum::body::Body>,
)),
)
.route(
crate::caller::endpoints::UPDATE_CONTACT_NAME,
patch(contact_endpoints::update_contact_names).route_layer(
axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>),
),
)
.route(
crate::caller::endpoints::ADD_MESSAGE,
post(message_endpoints::create_message).route_layer(axum::middleware::from_fn(
crate::auth::auth::<axum::body::Body>,
)),
)
.route(
crate::caller::endpoints::GET_MESSAGE,
get(message_endpoints::get_messages).route_layer(axum::middleware::from_fn(
crate::auth::auth::<axum::body::Body>,
)),
)
.route(
crate::caller::endpoints::SCHEDULE_MESSAGE,
post(scheduling_endpoints::schedule_message).route_layer(
axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>),
),
)
.route(
crate::caller::endpoints::GET_SCHEDULE_MESSAGE,
get(scheduling_endpoints::get_scheduled_messages).route_layer(
axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>),
),
)
.route(
crate::caller::endpoints::CREATE_SCHEDULED_MESSAGE_EVENT,
post(scheduling_endpoints::create_scheduled_message_event).route_layer(
axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>),
),
)
.route(
crate::caller::endpoints::GET_SCHEDULED_MESSAGE_EVENT,
get(scheduling_endpoints::get_scheduled_message_events).route_layer(
axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>),
),
)
.route(
crate::caller::endpoints::DELETE_SCHEDULED_MESSAGE_EVENT,
delete(scheduling_endpoints::delete_scheduled_message_event).route_layer(
axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>),
),
)
.route(
crate::caller::endpoints::UPDATE_SCHEDULED_MESSAGE_STATUS,
patch(scheduling_endpoints::update_scheduled_message_status).route_layer(
axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>),
),
)
.route(
crate::caller::endpoints::FETCH_SCHEDULED_MESSAGE,
get(scheduling_endpoints::fetch_scheduled_message).route_layer(
axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>),
),
)
.route(
crate::caller::endpoints::RECORD_MESSAGE_EVENT_RESPONSE,
post(event_endpoints::record_message_event_response).route_layer(
axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>),
),
)
.route(
crate::caller::endpoints::GET_MESSAGE_EVENT_RESPONSE,
get(event_endpoints::get_record_message_event_response).route_layer(
axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>),
),
)
.route(
crate::caller::endpoints::INSTANT_MESSAGE,
post(crate::caller::instant::endpoint::send_message).route_layer(
axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>),
),
)
.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)
}
}