From 8d8cdfe2671e744272d190ad9a7c262942c9bc42 Mon Sep 17 00:00:00 2001 From: Rohan Sircar Date: Wed, 12 Aug 2020 12:35:26 +0530 Subject: [PATCH] Changes to config Added appconfig struct Added option to chage hash cost from env file Added auto-reloading code --- src/main.rs | 35 +++++++++++++++++++++++++++++------ src/routes/auth.rs | 11 +++++------ src/routes/users.rs | 11 +++++++---- src/utils/auth.rs | 16 +++++++--------- 4 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/main.rs b/src/main.rs index 3fa960c..91d193b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,10 +7,7 @@ extern crate custom_error; extern crate regex; extern crate validator; -use actix_web::{ - middleware, web, App, HttpServer, -}; - +use actix_web::{middleware, web, App, HttpServer}; use actix_web_httpauth::middleware::HttpAuthentication; @@ -22,6 +19,8 @@ use actix_files as fs; use diesel::prelude::*; use diesel::r2d2::{self, ConnectionManager}; +use listenfd::ListenFd; +use types::DbPool; mod actions; mod errors; @@ -35,6 +34,11 @@ mod utils; #[macro_use] extern crate log; +#[derive(Clone)] +pub struct AppConfig { + hash_cost: u32, + pool: DbPool, +} #[actix_rt::main] async fn main() -> std::io::Result<()> { @@ -56,12 +60,22 @@ async fn main() -> std::io::Result<()> { diesel_migrations::run_pending_migrations(&pool.get().unwrap()) .expect("Error running migrations"); + let hash_cost = std::env::var("HASH_COST") + .map_err(|e| e.to_string()) + .and_then(|x| x.parse::().map_err(|e| e.to_string())) + .unwrap_or_else(|_| { + info!("Error parsing hash cost env variable, or it is not set. Using default cost of 8"); + 8 + }); + + let config: AppConfig = AppConfig { pool, hash_cost }; + let addr = std::env::var("BIND_ADDRESS").expect("BIND ADDRESS NOT FOUND"); info!("Starting server {}", addr); let private_key = rand::thread_rng().gen::<[u8; 32]>(); let app = move || { App::new() - .data(pool.clone()) + .data(config.clone()) .wrap(IdentityService::new( CookieIdentityPolicy::new(&private_key) .name("my-app-auth") @@ -82,5 +96,14 @@ async fn main() -> std::io::Result<()> { .service(routes::users::add_user) .service(fs::Files::new("/", "./static")) }; - HttpServer::new(app).bind(addr)?.run().await + // HttpServer::new(app).bind(addr)?.run().await + let mut listenfd = ListenFd::from_env(); + let mut server = HttpServer::new(app); + server = if let Some(l) = listenfd.take_tcp_listener(0).unwrap() { + server.listen(l)? + } else { + server.bind(addr)? + }; + + server.run().await } diff --git a/src/routes/auth.rs b/src/routes/auth.rs index 448030b..cbc5458 100644 --- a/src/routes/auth.rs +++ b/src/routes/auth.rs @@ -1,10 +1,8 @@ -use crate::types::DbPool; -// use actix_threadpool::BlockingError; use actix_web::{web, ResponseError}; use actix_web_httpauth::extractors::basic::BasicAuth; use crate::actions::users; -use crate::errors; +use crate::{errors, AppConfig}; use actix_identity::Identity; use actix_web::{get, Error, HttpResponse}; @@ -12,7 +10,7 @@ use actix_web::{get, Error, HttpResponse}; pub async fn login( id: Identity, credentials: BasicAuth, - pool: web::Data, + config: web::Data, ) -> Result { let maybe_identity = id.identity(); let response = if let Some(identity) = maybe_identity { @@ -22,7 +20,7 @@ pub async fn login( .json(format!("Already logged in as {}", identity))) } else { let credentials2 = credentials.clone(); - web::block(move || validate_basic_auth(credentials2, &pool)) + web::block(move || validate_basic_auth(credentials2, &config)) .await .and_then(|valid| { if valid { @@ -79,9 +77,10 @@ pub async fn index(id: Identity) -> String { /// basic auth middleware function pub fn validate_basic_auth( credentials: BasicAuth, - pool: &web::Data, + config: &web::Data, ) -> Result { let result = if let Some(password_ref) = credentials.password() { + let pool = &config.pool; let conn = pool.get()?; let password = password_ref.clone().into_owned(); let valid = users::verify_password( diff --git a/src/routes/users.rs b/src/routes/users.rs index 1c06f61..278642b 100644 --- a/src/routes/users.rs +++ b/src/routes/users.rs @@ -2,7 +2,7 @@ use actix_web::{get, post, web, HttpResponse}; use crate::actions; use crate::models; -use crate::types::DbPool; +use crate::AppConfig; use actix_web::error::ResponseError; use std::rc::Rc; use validator::Validate; @@ -10,12 +10,13 @@ use validator::Validate; /// Finds user by UID. #[get("/get/users/{user_id}")] pub async fn get_user( - pool: web::Data, + config: web::Data, user_id: web::Path, ) -> Result { let u_id = user_id.into_inner(); // use web::block to offload blocking Diesel code without blocking server thread let res = web::block(move || { + let pool = &config.pool; let conn = pool.get()?; actions::find_user_by_uid(u_id, &conn) }) @@ -34,10 +35,11 @@ pub async fn get_user( #[get("/get/users")] pub async fn get_all_users( - pool: web::Data, + config: web::Data, ) -> Result { // use web::block to offload blocking Diesel code without blocking server thread let res = web::block(move || { + let pool = &config.pool; let conn = pool.get()?; actions::get_all(&conn) }) @@ -65,12 +67,13 @@ pub async fn get_all_users( /// Inserts new user with name defined in form. #[post("/do_registration")] pub async fn add_user( - pool: web::Data, + config: web::Data, form: web::Json, ) -> Result { // use web::block to offload blocking Diesel code without blocking server thread let res = match form.0.validate() { Ok(_) => web::block(move || { + let pool = &config.pool; let conn = pool.get()?; actions::insert_new_user(Rc::new(form.0), &conn) }) diff --git a/src/utils/auth.rs b/src/utils/auth.rs index 2903097..bb8941b 100644 --- a/src/utils/auth.rs +++ b/src/utils/auth.rs @@ -1,8 +1,8 @@ -use actix_web_httpauth::extractors::basic::{BasicAuth, Config}; +use actix_web_httpauth::extractors::basic::BasicAuth; +use crate::AppConfig; // use actix_identity::Identity; -use crate::{routes::validate_basic_auth, types::DbPool}; -use actix_http::ResponseError; +use crate::routes::validate_basic_auth; use actix_threadpool::BlockingError; use actix_web::{dev::ServiceRequest, web, Error}; @@ -18,17 +18,15 @@ pub async fn validator( // verify credentials from db let credentials2 = credentials.clone(); // let pool = req.app_data(); - let pool = req - .app_data::() - .expect("Error getting db") - // .get_ref() - .clone(); + let config = req.app_data::().expect("Error getting db"); + // .get_ref() + // .clone(); // let _config = req // .app_data::() // .map(|data| data.get_ref().clone()) // .unwrap_or_else(Default::default); - let res = web::block(move || validate_basic_auth(credentials2, &pool)) + let res = web::block(move || validate_basic_auth(credentials2, &config)) .await .and_then(|valid| { if valid {