summaryrefslogtreecommitdiffstats
path: root/src/main.rs
blob: 03534798dc8cad5a7575d6cfb0700b5cee4f8bdd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate diesel_migrations;

use actix::prelude::*;
use actix_web::middleware::{errhandlers::ErrorHandlers, Logger};

use actix_identity::{CookieIdentityPolicy, IdentityService};
use actix_web::{http, web, App, HttpServer};

use chrono::Duration;
use diesel::mysql::MysqlConnection;
use dotenv::dotenv;
use r2d2_diesel::ConnectionManager;

mod public;
mod error;
mod error_handlers;
mod schema;
mod model;

use crate::model::DbExecutor;

embed_migrations!();

pub struct Secret(String);

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

    std::env::set_var(
        "RUST_LOG",
        "rgit=debug,actix_web=trace,actix_server=debug",
    );
    env_logger::init();

    let bind_host: String =
        std::env::var("BIND_HOST").unwrap_or_else(|_| "127.0.0.1:8000".to_string());

    let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    let manager = ConnectionManager::<MysqlConnection>::new(database_url);
    let pool = r2d2::Pool::builder()
        .build(manager)
        .expect("Can to build connection pool");
    embedded_migrations::run(&*pool.get().expect("Can connect to mysql"))
        .expect("Can run migrations");

    let db_addr: Addr<DbExecutor> = SyncArbiter::start(4, move || DbExecutor(pool.clone()));

    HttpServer::new(move || {
        let secret: String = std::env::var("SECRET_KEY").expect("SECRET_KEY env var should be set");
        let domain: String = std::env::var("DOMAIN").unwrap_or_else(|_| "localhost".to_string());
        let secure_cookies = &domain != "localhost";

        let error_handlers = ErrorHandlers::new()
            .handler(
                http::StatusCode::INTERNAL_SERVER_ERROR,
                error_handlers::internal_server_error,
            )
            .handler(http::StatusCode::BAD_REQUEST, error_handlers::bad_request)
            .handler(http::StatusCode::NOT_FOUND, error_handlers::not_found);

        App::new()
            .data(db_addr.clone())
            .data(Secret(secret.clone()))
            .wrap(error_handlers)
            .wrap(IdentityService::new(
                CookieIdentityPolicy::new(secret.as_bytes())
                    .name("rgit-session")
                    .domain(domain.as_str())
                    .max_age_time(Duration::days(30))
                    .secure(secure_cookies), // this has to reflect the usage of https
            ))
            .wrap(Logger::default())
            .route("/", web::get().to(public::index))
            .service(actix_files::Files::new("/static", "static/"))
    })
    .bind(&bind_host)?
    .run()
    .await?;

    Ok(())
}