use actix_files as fs; use actix_web::{App, HttpServer, web}; use actix_web::middleware::Logger; use tera::Tera; use std::io; use std::env; use lazy_static::lazy_static; mod config; mod controllers; mod middleware; mod models; mod routes; mod utils; // Import middleware components use middleware::{RequestTimer, SecurityHeaders, JwtAuth}; use utils::redis_service; use models::initialize_mock_data; // Initialize lazy_static for in-memory storage extern crate lazy_static; // Create a consistent session key lazy_static! { pub static ref SESSION_KEY: actix_web::cookie::Key = { // In production, this should be a proper secret key from environment variables let secret = std::env::var("SESSION_SECRET").unwrap_or_else(|_| { // Create a key that's at least 64 bytes long "my_secret_session_key_that_is_at_least_64_bytes_long_for_security_reasons_1234567890abcdef".to_string() }); // Ensure the key is at least 64 bytes let mut key_bytes = secret.as_bytes().to_vec(); while key_bytes.len() < 64 { key_bytes.extend_from_slice(b"0123456789abcdef"); } actix_web::cookie::Key::from(&key_bytes[0..64]) }; } #[actix_web::main] async fn main() -> io::Result<()> { // Initialize environment dotenv::dotenv().ok(); env_logger::init_from_env(env_logger::Env::default().default_filter_or("info")); // Load configuration let config = config::get_config(); // Check for port override from command line arguments let args: Vec = env::args().collect(); let mut port = config.server.port; for i in 1..args.len() { if args[i] == "--port" && i + 1 < args.len() { if let Ok(p) = args[i + 1].parse::() { port = p; break; } } } let bind_address = format!("{}:{}", config.server.host, port); // Initialize Redis client let redis_url = std::env::var("REDIS_URL").unwrap_or_else(|_| "redis://127.0.0.1:6379".to_string()); if let Err(e) = redis_service::init_redis_client(&redis_url) { log::error!("Failed to initialize Redis client: {}", e); log::warn!("Calendar functionality will not work properly without Redis"); } else { log::info!("Redis client initialized successfully"); } // Initialize mock data for DeFi operations initialize_mock_data(); log::info!("DeFi mock data initialized successfully"); log::info!("Starting server at http://{}", bind_address); // Create and configure the HTTP server HttpServer::new(move || { // Initialize Tera templates let mut tera = match Tera::new(&format!("{}/**/*.html", config.templates.dir)) { Ok(t) => t, Err(e) => { log::error!("Parsing error(s): {}", e); ::std::process::exit(1); } }; // Register custom Tera functions utils::register_tera_functions(&mut tera); App::new() // Enable logger middleware .wrap(Logger::default()) // Add custom middleware .wrap(RequestTimer) .wrap(SecurityHeaders) .wrap(JwtAuth) // Configure static files .service(fs::Files::new("/static", "./src/static")) // Add Tera template engine .app_data(web::Data::new(tera)) // Configure routes .configure(routes::configure_routes) }) .bind(bind_address)? .workers(num_cpus::get()) .run() .await }