use actix::Actor; use actix_identity::{CookieIdentityPolicy, IdentityService}; use actix_web::{App, get, HttpResponse, HttpServer, web}; use actix_web::cookie::SameSite; use actix_web::cookie::time::Duration; use actix_web::middleware::Logger; use clap::Parser; use basic_oidc::actors::bruteforce_actor::BruteForceActor; use basic_oidc::actors::openid_sessions_actor::OpenIDSessionsActor; use basic_oidc::actors::users_actor::UsersActor; use basic_oidc::constants::*; use basic_oidc::controllers::*; use basic_oidc::controllers::assets_controller::assets_route; use basic_oidc::controllers::login_controller::{login_route, logout_route}; use basic_oidc::data::app_config::AppConfig; use basic_oidc::data::client::ClientManager; use basic_oidc::data::entity_manager::EntityManager; use basic_oidc::data::user::{hash_password, User}; use basic_oidc::middlewares::auth_middleware::AuthMiddleware; #[get("/health")] async fn health() -> &'static str { "Running" } #[actix_web::main] async fn main() -> std::io::Result<()> { env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); let mut config: AppConfig = AppConfig::parse(); // In debug mode only, use dummy token if cfg!(debug_assertions) && config.token_key.is_empty() { config.token_key = String::from_utf8_lossy(&[32; 32]).to_string(); } if !config.storage_path().exists() { log::error!( "Specified storage path {:?} does not exists!", config.storage_path() ); panic!() } let mut users = EntityManager::::open_or_create(config.users_file()) .expect("Failed to load users list!"); // Create initial user if required if users.is_empty() { log::info!("Create default {} user", DEFAULT_ADMIN_USERNAME); let default_admin = User { username: DEFAULT_ADMIN_USERNAME.to_string(), password: hash_password(DEFAULT_ADMIN_PASSWORD).unwrap(), need_reset_password: true, authorized_clients: None, admin: true, ..Default::default() }; users .insert(default_admin) .expect("Failed to create initial user!"); } let users_actor = UsersActor::new(users).start(); let bruteforce_actor = BruteForceActor::default().start(); let openid_sessions_actor = OpenIDSessionsActor::default().start(); log::info!("Server will listen on {}", config.listen_address); let listen_address = config.listen_address.to_string(); HttpServer::new(move || { let clients = ClientManager::open_or_create(config.clients_file()) .expect("Failed to load clients list!"); let policy = CookieIdentityPolicy::new(config.token_key.as_bytes()) .name(SESSION_COOKIE_NAME) .secure(config.secure_cookie()) .visit_deadline(Duration::seconds(MAX_INACTIVITY_DURATION)) .login_deadline(Duration::seconds(MAX_SESSION_DURATION)) .same_site(SameSite::Lax); App::new() .app_data(web::Data::new(users_actor.clone())) .app_data(web::Data::new(bruteforce_actor.clone())) .app_data(web::Data::new(openid_sessions_actor.clone())) .app_data(web::Data::new(config.clone())) .app_data(web::Data::new(clients)) .wrap(Logger::default()) .wrap(AuthMiddleware {}) .wrap(IdentityService::new(policy)) // main route .route("/", web::get() .to(|| async { HttpResponse::Found().append_header(("Location", "/settings")).finish() })) // health route .service(health) // Assets serving .route("/assets/{path:.*}", web::get().to(assets_route)) // Login page .route("/login", web::get().to(login_route)) .route("/login", web::post().to(login_route)) // Logout page .route("/logout", web::get().to(logout_route)) // Settings routes .route("/settings", web::get().to(settings_controller::account_settings_details_route)) .route("/settings/change_password", web::get().to(settings_controller::change_password_route)) .route("/settings/change_password", web::post().to(settings_controller::change_password_route)) // Admin routes .route("/admin", web::get() .to(|| async { HttpResponse::Found().append_header(("Location", "/settings")).finish() })) .route("/admin/clients", web::get().to(admin_controller::clients_route)) .route("/admin/users", web::get().to(admin_controller::users_route)) .route("/admin/users", web::post().to(admin_controller::users_route)) .route("/admin/create_user", web::get().to(admin_controller::create_user)) .route("/admin/edit_user", web::get().to(admin_controller::edit_user)) // Admin API .route("/admin/api/find_username", web::post().to(admin_api::find_username)) .route("/admin/api/delete_user", web::post().to(admin_api::delete_user)) // OpenID routes .route("/.well-known/openid-configuration", web::get().to(openid_controller::get_configuration)) .route("/openid/authorize", web::get().to(openid_controller::authorize)) }) .bind(listen_address)? .run() .await }