use actix::Actor; use actix_cors::Cors; use actix_identity::config::LogoutBehaviour; use actix_identity::IdentityMiddleware; use actix_multipart::form::tempfile::TempFileConfig; use actix_multipart::form::MultipartFormConfig; use actix_remote_ip::RemoteIPConfig; use actix_session::storage::CookieSessionStore; use actix_session::SessionMiddleware; use actix_web::cookie::{Key, SameSite}; use actix_web::http::header; use actix_web::middleware::Logger; use actix_web::web::Data; use actix_web::{web, App, HttpServer}; use light_openid::basic_state_manager::BasicStateManager; use std::time::Duration; use virtweb_backend::actors::libvirt_actor::LibVirtActor; use virtweb_backend::app_config::AppConfig; use virtweb_backend::constants; use virtweb_backend::constants::{ MAX_INACTIVITY_DURATION, MAX_SESSION_DURATION, SESSION_COOKIE_NAME, }; use virtweb_backend::controllers::{ auth_controller, iso_controller, server_controller, vm_controller, }; use virtweb_backend::libvirt_client::LibVirtClient; use virtweb_backend::middlewares::auth_middleware::AuthChecker; use virtweb_backend::utils::files_utils; #[actix_web::main] async fn main() -> std::io::Result<()> { env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); log::debug!("Create required directory, if missing"); files_utils::create_directory_if_missing(&AppConfig::get().iso_storage_path()).unwrap(); let conn = Data::new(LibVirtClient( LibVirtActor::connect() .await .expect("Failed to connect to hypervisor!") .start(), )); log::info!("Start to listen on {}", AppConfig::get().listen_address); let state_manager = Data::new(BasicStateManager::new()); HttpServer::new(move || { let session_mw = SessionMiddleware::builder( CookieSessionStore::default(), Key::from(AppConfig::get().secret().as_bytes()), ) .cookie_name(SESSION_COOKIE_NAME.to_string()) .cookie_secure(AppConfig::get().cookie_secure) .cookie_same_site(SameSite::Strict) .cookie_domain(AppConfig::get().cookie_domain()) .cookie_http_only(true) .build(); let identity_middleware = IdentityMiddleware::builder() .logout_behaviour(LogoutBehaviour::PurgeSession) .visit_deadline(Some(Duration::from_secs(MAX_INACTIVITY_DURATION))) .login_deadline(Some(Duration::from_secs(MAX_SESSION_DURATION))) .build(); let cors = Cors::default() .allowed_origin(&AppConfig::get().website_origin) .allowed_methods(vec!["GET", "POST", "DELETE", "PUT"]) .allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT]) .allowed_header(header::CONTENT_TYPE) .supports_credentials() .max_age(3600); App::new() .wrap(Logger::default()) .wrap(AuthChecker) .wrap(identity_middleware) .wrap(session_mw) .wrap(cors) .app_data(state_manager.clone()) .app_data(Data::new(RemoteIPConfig { proxy: AppConfig::get().proxy_ip.clone(), })) .app_data(conn.clone()) // Uploaded files .app_data(MultipartFormConfig::default().total_limit(constants::ISO_MAX_SIZE)) .app_data(TempFileConfig::default().directory(&AppConfig::get().temp_dir)) // Server controller .route("/", web::get().to(server_controller::root_index)) .route( "/api/server/static_config", web::get().to(server_controller::static_config), ) .route( "/api/server/info", web::get().to(server_controller::server_info), ) // Auth controller .route( "/api/auth/local", web::post().to(auth_controller::local_auth), ) .route( "/api/auth/start_oidc", web::get().to(auth_controller::start_oidc), ) .route( "/api/auth/finish_oidc", web::post().to(auth_controller::finish_oidc), ) .route( "/api/auth/user", web::get().to(auth_controller::current_user), ) .route( "/api/auth/sign_out", web::get().to(auth_controller::sign_out), ) // ISO controller .route( "/api/iso/upload", web::post().to(iso_controller::upload_file), ) .route( "/api/iso/upload_from_url", web::post().to(iso_controller::upload_from_url), ) .route("/api/iso/list", web::get().to(iso_controller::get_list)) .route( "/api/iso/{filename}", web::get().to(iso_controller::download_file), ) .route( "/api/iso/{filename}", web::delete().to(iso_controller::delete_file), ) // Virtual machines controller .route("/api/vm/create", web::post().to(vm_controller::create)) .route("/api/vm/list", web::get().to(vm_controller::list_all)) .route("/api/vm/{uid}", web::get().to(vm_controller::get_single)) }) .bind(&AppConfig::get().listen_address)? .run() .await }