// SPDX-FileCopyrightText: 2024 Simon Bruder // // SPDX-License-Identifier: AGPL-3.0-or-later use actix_identity::IdentityMiddleware; use actix_session::{storage::CookieSessionStore, SessionMiddleware}; use actix_web::middleware::ErrorHandlers; use actix_web::{cookie::Key, http::StatusCode, web, App, HttpResponse, HttpServer}; use base64::prelude::{Engine as _, BASE64_STANDARD}; use clap::Parser; use log::{info, warn}; use mime_guess::from_path; use rust_embed::Embed; use li7y::Config; #[derive(Embed)] #[folder = "static"] struct Static; #[actix_web::main] async fn main() -> std::io::Result<()> { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); let config = Config::parse(); let secret_key = match config.secret_key { Some(ref encoded) => Key::from( &BASE64_STANDARD .decode(encoded) .expect("failed to decode base64 in SECRET_KEY"), ), None => { warn!("SECRET_KEY was not specified, using randomly generated key"); Key::generate() } }; let pool: sqlx::PgPool = sqlx::Pool::::connect(&config.database_url) .await .expect("failed to connect to database"); sqlx::migrate!() .run(&pool) .await .expect("failed to run migrations"); let address = config.listen_address; let port = config.listen_port; info!("Starting on {address}:{port}"); HttpServer::new(move || { App::new() .app_data(web::Data::new(config.clone())) .app_data(web::Data::new(pool.clone())) .service(web::scope("/static").route( "/{_:.*}", web::get().to(|path: web::Path| async { Static::get(&path) .map(|embedded_file| match from_path(path.into_inner()).first() { Some(mime_type) => HttpResponse::Ok() .content_type(mime_type) .body(embedded_file.data), None => HttpResponse::Ok().body(embedded_file.data), }) .unwrap_or(HttpResponse::NotFound().body(())) }), )) .configure(li7y::frontend::config) .wrap(ErrorHandlers::new().handler( StatusCode::UNAUTHORIZED, li7y::middleware::error_handlers::redirect_to_login, )) .wrap(IdentityMiddleware::default()) .wrap(SessionMiddleware::new( CookieSessionStore::default(), secret_key.clone(), )) }) .bind((address, port))? .run() .await }