Changes to config

Added appconfig struct
Added option to chage hash cost from env file
Added auto-reloading code
This commit is contained in:
Rohan Sircar 2020-08-12 12:35:26 +05:30
parent 7683636a4e
commit 8d8cdfe267
4 changed files with 48 additions and 25 deletions

View File

@ -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::<u32>().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
}

View File

@ -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<DbPool>,
config: web::Data<AppConfig>,
) -> Result<HttpResponse, impl ResponseError> {
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<DbPool>,
config: &web::Data<AppConfig>,
) -> Result<bool, errors::DomainError> {
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(

View File

@ -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<DbPool>,
config: web::Data<AppConfig>,
user_id: web::Path<i32>,
) -> Result<HttpResponse, impl ResponseError> {
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<DbPool>,
config: web::Data<AppConfig>,
) -> Result<HttpResponse, impl ResponseError> {
// 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<DbPool>,
config: web::Data<AppConfig>,
form: web::Json<models::NewUser>,
) -> Result<HttpResponse, impl ResponseError> {
// 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)
})

View File

@ -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::<DbPool>()
.expect("Error getting db")
// .get_ref()
.clone();
let config = req.app_data::<AppConfig>().expect("Error getting db");
// .get_ref()
// .clone();
// let _config = req
// .app_data::<Config>()
// .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 {