use std::error::Error; use std::fs; use std::path::Path; use dotenvy::dotenv; use log::{error, info}; use rocket::{catchers, routes}; use sqlx::migrate::Migrator; use sqlx::postgres::PgPoolOptions; use crate::config::TFConfig; pub mod format; pub mod util; pub mod db; pub mod config; pub mod tokens; pub mod routes; pub mod auth; static MIGRATOR: Migrator = sqlx::migrate!(); #[rocket::main] async fn main() -> Result<(), Box> { let _ = rocket::build(); info!("[tfapi] loading config"); let _ = dotenv(); if std::env::var("CONFIG_FILE").is_err() && !Path::new("config.toml").exists() { error!("[tfapi] fatal: the environment variable CONFIG_FILE is not set"); error!("[tfapi] help: try creating a .env file that sets it"); error!("[tfapi] help: or, create a file config.toml with your config, as it is loaded automatically"); std::process::exit(1); } let config_file = if Path::new("config.toml").exists() { "config.toml".to_string() } else { std::env::var("CONFIG_FILE").unwrap() }; let config_data = match fs::read_to_string(&config_file) { Ok(d) => d, Err(e) => { error!("[tfapi] fatal: unable to read config from {}", config_file); error!("[tfapi] fatal: {}", e); std::process::exit(1); } }; let config: TFConfig = match toml::from_str(&config_data) { Ok(c) => c, Err(e) => { error!("[tfapi] fatal: unable to parse config from {}", config_file); error!("[tfapi] fatal: {}", e); std::process::exit(1); } }; info!("[tfapi] connecting to database pool"); let pool = match PgPoolOptions::new().max_connections(5).connect(&config.db_url).await { Ok(p) => p, Err(e) => { error!("[tfapi] fatal: unable to connect to database pool"); error!("[tfapi] fatal: {}", e); std::process::exit(1); } }; info!("[tfapi] running database migrations"); MIGRATOR.run(&pool).await?; info!("[tfapi] building rocket config"); let figment = rocket::Config::figment().merge(("port", config.listen_port)); let _ = rocket::custom(figment) .mount("/", routes![ crate::routes::v1::auth::magic_link::magiclink_request, crate::routes::v1::signup::signup_request, crate::routes::v1::auth::verify_magic_link::verify_magic_link, crate::routes::v1::totp_authenticators::totp_authenticators_request, crate::routes::v1::verify_totp_authenticator::verify_totp_authenticator_request ]) .register("/", catchers![ crate::routes::handler_400, crate::routes::handler_401, crate::routes::handler_403, crate::routes::handler_404, crate::routes::handler_422, crate::routes::handler_500, crate::routes::handler_501, crate::routes::handler_502, crate::routes::handler_503, crate::routes::handler_504, crate::routes::handler_505, ]) .manage(pool) .manage(config) .launch().await?; Ok(()) }