1
0
mirror of https://github.com/actix/examples synced 2025-02-13 14:02:19 +01:00

87 lines
2.5 KiB
Rust
Raw Normal View History

2019-06-17 12:48:03 +06:00
use actix_identity::Identity;
use actix_web::{
2019-07-18 18:03:19 +06:00
dev::Payload, error::BlockingError, web, Error, FromRequest, HttpRequest,
HttpResponse,
};
use diesel::prelude::*;
use diesel::PgConnection;
use futures::future::{err, ok, Ready};
use serde::Deserialize;
2019-03-29 13:43:03 -07:00
use crate::errors::ServiceError;
use crate::models::{Pool, SlimUser, User};
use crate::utils::verify;
#[derive(Debug, Deserialize)]
pub struct AuthData {
pub email: String,
pub password: String,
}
// we need the same data
// simple aliasing makes the intentions clear and its more readable
pub type LoggedUser = SlimUser;
2019-04-14 10:34:41 -07:00
impl FromRequest for LoggedUser {
type Config = ();
2019-03-29 13:43:03 -07:00
type Error = Error;
type Future = Ready<Result<LoggedUser, Error>>;
2019-03-29 13:43:03 -07:00
2019-04-14 10:34:41 -07:00
fn from_request(req: &HttpRequest, pl: &mut Payload) -> Self::Future {
if let Ok(identity) = Identity::from_request(req, pl).into_inner() {
if let Some(user_json) = identity.identity() {
if let Ok(user) = serde_json::from_str(&user_json) {
return ok(user);
}
}
}
err(ServiceError::Unauthorized.into())
}
}
2019-12-07 23:59:24 +06:00
pub async fn logout(id: Identity) -> HttpResponse {
id.forget();
HttpResponse::Ok().finish()
}
2019-12-07 23:59:24 +06:00
pub async fn login(
auth_data: web::Json<AuthData>,
id: Identity,
pool: web::Data<Pool>,
2019-12-07 23:59:24 +06:00
) -> Result<HttpResponse, ServiceError> {
let res = web::block(move || query(auth_data.into_inner(), pool)).await;
match res {
Ok(user) => {
let user_string = serde_json::to_string(&user).unwrap();
id.remember(user_string);
Ok(HttpResponse::Ok().finish())
}
Err(err) => match err {
BlockingError::Error(service_error) => Err(service_error),
BlockingError::Canceled => Err(ServiceError::InternalServerError),
},
2019-12-07 23:59:24 +06:00
}
}
2019-12-07 23:59:24 +06:00
pub async fn get_me(logged_user: LoggedUser) -> HttpResponse {
HttpResponse::Ok().json(logged_user)
}
/// Diesel query
fn query(auth_data: AuthData, pool: web::Data<Pool>) -> Result<SlimUser, ServiceError> {
use crate::schema::users::dsl::{email, users};
let conn: &PgConnection = &pool.get().unwrap();
let mut items = users
.filter(email.eq(&auth_data.email))
.load::<User>(conn)?;
if let Some(user) = items.pop() {
if let Ok(matching) = verify(&user.hash, &auth_data.password) {
if matching {
return Ok(user.into());
}
}
}
Err(ServiceError::Unauthorized)
}