Browse Source

Formatting and diesel boxed query experiment

devel
Rohan Sircar 4 years ago
parent
commit
e22b6770f9
  1. 2
      src/.cargo/config
  2. 61
      src/actions/users.rs
  3. 20
      src/errors/domain_error.rs
  4. 14
      src/main.rs
  5. 20
      src/routes/auth.rs
  6. 3
      src/utils/regexs.rs

2
src/.cargo/config

@ -0,0 +1,2 @@
[target.aarch64-unknown-linux-gnu]
linker = 'aarch64-linux-gnu-gcc'

61
src/actions/users.rs

@ -1,5 +1,4 @@
use diesel::prelude::*; use diesel::prelude::*;
use diesel::sqlite::Sqlite;
use crate::errors; use crate::errors;
use crate::models; use crate::models;
@ -25,7 +24,7 @@ pub fn _find_user_by_name(
user_name: String, user_name: String,
conn: &SqliteConnection, conn: &SqliteConnection,
) -> Result<Option<models::UserDTO>, errors::DomainError> { ) -> Result<Option<models::UserDTO>, errors::DomainError> {
let maybe_user = _get_user_by_name(user_name)
let maybe_user = query::_get_user_by_name(&user_name)
.first::<models::UserDTO>(conn) .first::<models::UserDTO>(conn)
.optional(); .optional();
@ -51,35 +50,20 @@ pub fn insert_new_user(
// modules inside a function's scope (rather than the normal module's scope) // modules inside a function's scope (rather than the normal module's scope)
// to prevent import collisions and namespace pollution. // to prevent import collisions and namespace pollution.
use crate::schema::users::dsl::*; use crate::schema::users::dsl::*;
// let new_user = models::User {
// id: Uuid::new_v4().to_string(),
// name: nu.name.to_string(),
// };
// let x = users.load::<models::User>(conn).optional();
// let target = users.find("4");
// let test_user = models::User {
// id: "5".to_owned(),
// name: "who".to_owned(),
// };
// let update_result = diesel::update(target).set(&test_user).execute(conn);
// let mut nu2 = nu.clone();
let mut nu2 = Rc::make_mut(&mut nu); let mut nu2 = Rc::make_mut(&mut nu);
nu2.password = hash(nu2.password.clone(), DEFAULT_COST)?;
nu2.password = hash(&nu2.password, DEFAULT_COST)?;
diesel::insert_into(users) diesel::insert_into(users)
.values(nu.as_ref()) .values(nu.as_ref())
.execute(conn)?; .execute(conn)?;
let user = let user =
_get_user_by_name(nu.name.clone()).first::<models::UserDTO>(conn)?;
query::_get_user_by_name(&nu.name).first::<models::UserDTO>(conn)?;
Ok(user) Ok(user)
} }
pub fn verify_password(
user_name: String,
given_password: String,
pub fn verify_password<'a>(
user_name: &'a String,
given_password: &'a String,
conn: &SqliteConnection, conn: &SqliteConnection,
) -> Result<bool, errors::DomainError> { ) -> Result<bool, errors::DomainError> {
use crate::schema::users::dsl::*; use crate::schema::users::dsl::*;
@ -87,18 +71,25 @@ pub fn verify_password(
.select(password) .select(password)
.filter(name.eq(user_name)) .filter(name.eq(user_name))
.first::<String>(conn)?; .first::<String>(conn)?;
Ok(verify(given_password.as_str(), password_hash.as_str())?)
Ok(verify(given_password, password_hash.as_str())?)
} }
fn _get_user_by_name(
user_name: String,
) -> crate::schema::users::BoxedQuery<
'static,
Sqlite,
(diesel::sql_types::Text, diesel::sql_types::Timestamp),
> {
use crate::schema::users::dsl::*;
users
.select((name, created_at))
.filter(name.eq(user_name))
.into_boxed()
mod query {
use diesel::prelude::*;
use diesel::sql_types::Text;
use diesel::sql_types::Timestamp;
use diesel::sqlite::Sqlite;
/// <'a, B, T> where a = lifetime, B = Backend, T = SQL data types
type Query<'a, B, T> = crate::schema::users::BoxedQuery<'a, B, T>;
pub fn _get_user_by_name<'a>(
user_name: &'a String,
) -> Query<'a, Sqlite, (Text, Timestamp)> {
use crate::schema::users::dsl::*;
users
.select((name, created_at))
.filter(name.eq(user_name))
.into_boxed()
}
} }

20
src/errors/domain_error.rs

@ -53,14 +53,18 @@ impl ResponseError for DomainError {
reason: format!("{} {}", err.to_string(), source).as_str(), reason: format!("{} {}", err.to_string(), source).as_str(),
}) })
} }
DomainError::PasswordError { cause } => HttpResponse::BadRequest().json(ErrorModel {
error_code: 400,
reason: format!("{} {}, ", err.to_string(), cause.clone()).as_str(),
}),
DomainError::GenericError { cause } => HttpResponse::BadRequest().json(ErrorModel {
error_code: 400,
reason: format!("{} {}, ", err.to_string(), cause.clone()).as_str(),
}),
DomainError::PasswordError { cause } => HttpResponse::BadRequest()
.json(ErrorModel {
error_code: 400,
reason: format!("{} {}, ", err.to_string(), cause.clone())
.as_str(),
}),
DomainError::GenericError { cause } => HttpResponse::BadRequest()
.json(ErrorModel {
error_code: 400,
reason: format!("{} {}, ", err.to_string(), cause.clone())
.as_str(),
}),
} }
} }
} }

14
src/main.rs

@ -11,7 +11,9 @@ extern crate custom_error;
extern crate regex; extern crate regex;
extern crate validator; extern crate validator;
use actix_web::{error, get, middleware, post, web, App, Error, HttpResponse, HttpServer};
use actix_web::{
error, get, middleware, post, web, App, Error, HttpResponse, HttpServer,
};
use yarte::Template; use yarte::Template;
@ -61,7 +63,9 @@ async fn index(info: web::Path<(u32, String)>) -> Result<HttpResponse, Error> {
template template
.call() .call()
.map(|body| HttpResponse::Ok().content_type("text/html").body(body)) .map(|body| HttpResponse::Ok().content_type("text/html").body(body))
.map_err(|_| error::ErrorInternalServerError("Error while parsing template"))
.map_err(|_| {
error::ErrorInternalServerError("Error while parsing template")
})
} }
/// This handler uses json extractor /// This handler uses json extractor
@ -85,10 +89,12 @@ async fn main() -> std::io::Result<()> {
env_logger::init(); env_logger::init();
dotenv::dotenv().ok(); dotenv::dotenv().ok();
let basic_auth_middleware = HttpAuthentication::basic(utils::auth::validator);
let basic_auth_middleware =
HttpAuthentication::basic(utils::auth::validator);
// set up database connection pool // set up database connection pool
let connspec = std::env::var("DATABASE_URL").expect("DATABASE_URL NOT FOUND");
let connspec =
std::env::var("DATABASE_URL").expect("DATABASE_URL NOT FOUND");
let manager = ConnectionManager::<SqliteConnection>::new(connspec); let manager = ConnectionManager::<SqliteConnection>::new(connspec);
let pool = r2d2::Pool::builder() let pool = r2d2::Pool::builder()
.build(manager) .build(manager)

20
src/routes/auth.rs

@ -1,5 +1,5 @@
use crate::types::DbPool; use crate::types::DbPool;
use actix_threadpool::BlockingError;
// use actix_threadpool::BlockingError;
use actix_web::{web, ResponseError}; use actix_web::{web, ResponseError};
use actix_web_httpauth::extractors::basic::BasicAuth; use actix_web_httpauth::extractors::basic::BasicAuth;
@ -29,10 +29,16 @@ pub async fn login(
id.remember(credentials.user_id().to_string()); id.remember(credentials.user_id().to_string());
Ok(HttpResponse::Found().header("location", "/").finish()) Ok(HttpResponse::Found().header("location", "/").finish())
} else { } else {
Err(BlockingError::Error(
errors::DomainError::new_password_error(
"Wrong password or account does not exist"
.to_string(),
// Err(BlockingError::Error(
// errors::DomainError::new_password_error(
// "Wrong password or account does not exist"
// .to_string(),
// ),
// ))
Ok(HttpResponse::BadRequest().json(
crate::models::errors::ErrorModel::new(
20,
"Wrong password or account does not exist",
), ),
)) ))
} }
@ -78,8 +84,8 @@ fn validate_basic_auth(
let conn = pool.get()?; let conn = pool.get()?;
let password = password_ref.clone().into_owned(); let password = password_ref.clone().into_owned();
let valid = users::verify_password( let valid = users::verify_password(
credentials.user_id().clone().into_owned(),
password,
&credentials.user_id().clone().into_owned(),
&password,
&conn, &conn,
)?; )?;
Ok(valid) Ok(valid)

3
src/utils/regexs.rs

@ -1,5 +1,6 @@
use lazy_static::lazy_static; use lazy_static::lazy_static;
use regex::Regex; use regex::Regex;
lazy_static! { lazy_static! {
pub static ref USERNAME_REG: Regex = Regex::new(r"^([a-z\d]+-)*[a-z\d]+$").unwrap();
pub static ref USERNAME_REG: Regex =
Regex::new(r"^([a-z\d]+-)*[a-z\d]+$").unwrap();
} }
Loading…
Cancel
Save