use actix::{Handler, Message}; use diesel::prelude::*; use errors::ServiceError; use models::{DbExecutor, User, SlimUser}; use bcrypt::verify; use actix_web::{FromRequest, HttpRequest, middleware::identity::RequestIdentity}; use utils::decode_token; #[derive(Debug, Deserialize)] pub struct AuthData { pub email: String, pub password: String, } impl Message for AuthData { type Result = Result; } impl Handler for DbExecutor { type Result = Result; fn handle(&mut self, msg: AuthData, _: &mut Self::Context) -> Self::Result { use schema::users::dsl::{users, email}; let conn: &PgConnection = &self.0.get().unwrap(); let mut items = users .filter(email.eq(&msg.email)) .load::(conn)?; if let Some(user) = items.pop() { match verify(&msg.password, &user.password) { Ok(matching) => if matching { return Ok(user.into()); }, Err(_) => (), } } Err(ServiceError::BadRequest("Username and Password don't match".into())) } } // we need the same data // simple aliasing makes the intentions clear and its more readable pub type LoggedUser = SlimUser; impl FromRequest for LoggedUser { type Config = (); type Result = Result; fn from_request(req: &HttpRequest, _: &Self::Config) -> Self::Result { if let Some(identity) = req.identity() { let user: SlimUser = decode_token(&identity)?; return Ok(user as LoggedUser); } Err(ServiceError::Unauthorized) } }