use std::{env, io, net::SocketAddrV4, sync::Arc}; // use actix_cors::Cors; use actix_identity::IdentityMiddleware; use actix_session::{config::PersistentSession, storage::CookieSessionStore, SessionMiddleware}; use actix_web::{ cookie::{time::Duration, Key}, middleware, web::{self}, App, HttpServer, }; // Define our model module mod model; use model::user::User; // Define our repo module mod repo; // use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; use repo::todo_repository::TodoRepository; use repo::user_repository::UserRepository; // Define our routes module mod routes; use routes::{todo_routes, user_routes}; /// Server address if none is given via ENV: WEBSERVER_ADDRESS static DEFAULT_WEBSERVER_ADDRESS: &str = "127.0.0.1"; /// Server port if none is given via ENV: WEBSERVER_PORT static DEFAULT_WEBSERVER_PORT: &str = "6969"; /// Starts the webserver and initializes required repos, etc. #[actix_web::main] async fn main() -> io::Result<()> { env_logger::init_from_env(env_logger::Env::new().default_filter_or("debug")); // TODO: Currently I do not handle the case where the cassandra server is // rebooted during the lifetime of the webserver and loses its configuration. // Normally this is not a real scenario because the tables should be persistent // througout reboots but idk, it would still be cool to handle this gracefully. // What would have to happen is a reinit of the repo classes after the connection // is regained to reinitialize the perhaps missing keyspaces/tables let cassandra_session = Arc::new(repo::init()); // TODO: web::Data is already an Arc //-> Investigate if we really need the session as an Arc as well let user = User::new("admin", "nimda", "salzig"); let user_repo = web::Data::new(UserRepository::new(Arc::clone(&cassandra_session))); if let Err(err) = user_repo.create(&user) { log::debug!("Default user already exists: {err}"); } let todo_repo = web::Data::new(TodoRepository::new(Arc::clone(&cassandra_session))); // Secret key used to init session storage let key = Key::generate(); // External ENV params let socket_addr: SocketAddrV4 = format!( "{}:{}", env::var("WEBSERVER_ADDRESS").unwrap_or(DEFAULT_WEBSERVER_ADDRESS.to_string()), env::var("WEBSERVER_PORT").unwrap_or(DEFAULT_WEBSERVER_PORT.to_string()) ) .parse() .expect("A valid socket address. Check your ENV variables!"); // HOLY: Ich werde jetzt dann wirklich gleich verrückt mit CORS & Cookies... // ICH WILL DOCH NUR DAS FRONTEND LOKAL TESTEN... IST DASS DENN ZU VIEL VERLANGT? // TODO: Remove after local dev // openssl req -x509 -newkey rsa:4096 -nodes -keyout key.pem -out cert.pem -days 365 -subj '/CN=localhost' // Move to /cert/... in container // let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls())?; // builder.set_private_key_file("/cert/key.pem", SslFiletype::PEM)?; // builder.set_certificate_chain_file("/cert/cert.pem")?; log::info!( "Starting HTTP server: http://{}:{}", socket_addr.ip(), socket_addr.port() ); HttpServer::new(move || { App::new() .wrap(middleware::Compress::default()) .wrap(IdentityMiddleware::default()) .wrap( SessionMiddleware::builder(CookieSessionStore::default(), key.clone()) .cookie_secure(false) // TODO: Remove after development with local solidjs app // .cookie_secure(true) // .cookie_same_site(actix_web::cookie::SameSite::None) // Session lifetime .session_lifecycle(PersistentSession::default().session_ttl(Duration::days(7))) .build(), ) // TODO: Remove after development with local solidjs app // .wrap( // Cors::default() // .allowed_origin("http://localhost:3000") // .supports_credentials() // .allow_any_method() // .allow_any_header(), // ) .wrap(middleware::Logger::default()) .app_data(user_repo.clone()) .app_data(todo_repo.clone()) .service(user_routes::get_user) .service(user_routes::put_user) .service(user_routes::post_user) .service(todo_routes::get_todo) .service(todo_routes::put_todo) .service(todo_routes::delete_todo) .service(routes::post_login) .service(routes::delete_logout) .default_service(web::to(routes::index)) }) .bind(socket_addr)? // TODO: Remove after local dev // .bind_openssl(socket_addr, builder)? .workers(2) // number of workers per bind default ist #cpus .run() .await }