Skip to content
mod assets;
mod auth;
mod db;
mod handlers;
mod templates;

use actix_web::{App, HttpResponse, HttpServer, get, web};
use db::DbConfig;

const VERSION: &str = env!("CARGO_PKG_VERSION");

fn letter_banner(port: u16) -> String {
    let url = format!("http://0.0.0.0:{}", port);
    format!(
        "\n  L  v{version}\n     {url}\n",
        version = VERSION,
        url = url,
    )
}

#[get("/up")]
async fn up() -> HttpResponse {
    HttpResponse::Ok().finish()
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    dotenvy::dotenv().ok();
    env_logger::init();

    let port: u16 = std::env::var("PORT")
        .ok()
        .and_then(|s| s.parse().ok())
        .unwrap_or(8080);

    print!("{}", letter_banner(port));

    let db_config = DbConfig::from_env().expect("Failed to configure database from environment");

    match db_config.run_migrations().await {
        Ok(()) => log::info!("Migrations completed"),
        Err(e) => log::error!("Migration error: {e}"),
    }

    let db_data = web::Data::new(db_config);

    HttpServer::new(move || {
        App::new()
            .app_data(db_data.clone())
            .service(up)
            .service(assets::assets)
            .service(handlers::index)
            .service(handlers::audiences)
            .service(handlers::login_page)
            .service(handlers::login_post)
            .service(handlers::logout_post)
            .service(handlers::invite_page)
            .service(handlers::invite_post)
            .service(handlers::register_redirect)
            .service(handlers::register_page)
            .service(handlers::register_post)
            .service(handlers::dashboard)
            .service(handlers::new_article_page)
            .service(handlers::create_article)
            .service(handlers::edit_article_page)
            .service(handlers::commit_article)
            .service(handlers::publish_article)
            .service(handlers::audience_page)
            .service(handlers::article_page)
            .service(handlers::new_audience_page)
            .service(handlers::create_audience)
    })
    .bind(("0.0.0.0", port))?
    .run()
    .await
}

#[cfg(test)]
mod tests {
    use actix_web::{App, http::StatusCode, test};

    use super::*;

    #[actix_web::test]
    async fn test_up_get() {
        let app = test::init_service(App::new().service(up)).await;
        let req = test::TestRequest::get().uri("/up").to_request();
        let resp = test::call_service(&app, req).await;
        assert_eq!(resp.status(), StatusCode::OK);
    }

    #[actix_web::test]
    async fn test_up_post() {
        let app = test::init_service(App::new().service(up)).await;
        let req = test::TestRequest::post().uri("/up").to_request();
        let resp = test::call_service(&app, req).await;
        assert!(resp.status().is_client_error());
    }
}