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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate diesel_migrations;
use std::fs::File;
use std::io::Read;
use actix::prelude::*;
use actix_web::middleware::{errhandlers::ErrorHandlers, Logger};
use actix_identity::{CookieIdentityPolicy, IdentityService};
use actix_web::{http, web, App, HttpServer};
use argonautica::{Hasher, Verifier};
use chrono::Duration;
use diesel::mysql::MysqlConnection;
use dotenv::dotenv;
use r2d2_diesel::ConnectionManager;
mod admin;
mod error;
mod error_handlers;
mod model;
mod schema;
mod user;
mod util;
use crate::admin::user_creation::PassHashExecutor;
use crate::model::DbExecutor;
use crate::user::login::HashVerifyExecutor;
embed_migrations!();
pub struct Secret(String);
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
dotenv().ok();
std::env::set_var(
"RUST_LOG",
"joklerpoint=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()));
let verifier_addr: Addr<HashVerifyExecutor> =
SyncArbiter::start(4, move || HashVerifyExecutor(Verifier::default()));
let hasher_addr: Addr<PassHashExecutor> =
SyncArbiter::start(4, move || PassHashExecutor(Hasher::default()));
HttpServer::new(move || {
let secret = if let Ok(path) = std::env::var("SECRET_KEY_FILE") {
let mut file = File::open(path).expect("SECRET_KEY_FILE openable");
let mut content = String::new();
file.read_to_string(&mut content)
.expect("SECRET_KEY_FILE content readable");
content.trim();
content
} else {
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(verifier_addr.clone())
.data(hasher_addr.clone())
.data(Secret(secret.clone()))
.wrap(error_handlers)
.wrap(IdentityService::new(
CookieIdentityPolicy::new(secret.as_bytes())
.name("jkp-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(user::index))
.service(
web::resource("/login")
.route(web::get().to(user::login))
.route(web::post().to(user::confirm_login)),
)
.route("/transactions", web::get().to(user::transactions))
.service(
web::resource("/transfer")
.route(web::get().to(user::transfer))
.route(web::post().to(user::confirm_transfer)),
)
.route("/settings", web::get().to(user::settings))
.route("/reset-password", web::post().to(user::reset_password))
.route("/logout", web::get().to(user::logout))
.route("/admin", web::get().to(admin::handle_index))
.service(
web::scope("/admin")
.route("/create-user", web::post().to(admin::handle_create_user))
.route(
"/change-password",
web::post().to(admin::handle_change_password),
),
)
.service(actix_files::Files::new("/static", "static/"))
})
.bind(&bind_host)?
.run()
.await?;
Ok(())
}
|