#![warn(clippy::pedantic)] mod auth; mod config; mod errors; mod extractor_helper; mod files; mod routes; use axum::{middleware, Router}; use axum_jwks::Jwks; use std::env; use std::process::exit; use std::str::FromStr; use tracing::{debug, error, info}; #[derive(Clone)] pub struct AppState { config: config::Config, pub jwks: Jwks, } #[tokio::main] async fn main() { tracing_subscriber::fmt() .with_max_level(get_log_level()) .init(); let config = config::get_config(); match config { Ok(config) => { debug!("Config loaded {:?}", &config,); let jwks = Jwks::from_oidc_url( // The Authorization Server that signs the JWTs you want to consume. &config.oidc.oidc_endpoint, // The audience identifier for the application. This ensures that // JWTs are intended for this application. None, ) .await .unwrap(); let bind = format!("{}:{}", &config.server.bind_address, &config.server.port); let state = AppState { config, jwks }; let app = Router::new() .merge(routes::routes()) .route_layer(middleware::from_fn_with_state( state.clone(), auth::validate_token, )) .with_state(state); let listener = tokio::net::TcpListener::bind(bind).await.unwrap(); info!("listening on {}", listener.local_addr().unwrap()); axum::serve(listener, app).await.unwrap(); } Err(error) => { error!( "Error while loading config: {}. Tried loading from the following files {:?} and env variables prefixed by CASKET_.", error, config::CONFIG_LOCATIONS ); exit(1) } } } fn get_log_level() -> tracing::Level { let env = env::var("CASKET_LOG_LEVEL"); match env { Ok(value) => tracing::Level::from_str(&value) .unwrap_or_else(|_| panic!("Failed to parse log level env {value}")), Err(_) => tracing::Level::INFO, } }