use actix_identity::Identity; use actix_session::Session; use actix_web::{ delete, http::{header::ContentType, Method}, post, web, HttpRequest, HttpResponse, Responder, HttpMessage, }; use crate::{model::user::User, repo::user_repository::UserRepository}; pub mod todo_routes; pub mod user_routes; /// Helper function to get a valid User from session. fn get_user_from_session(session: Session) -> Option { match session.get::("user") { Ok(Some(user)) => Some(user), Ok(None) => { log::warn!("Could no DESERIALIZE user from session despite someone is logged in"); None } Err(err) => { log::warn!("Could no GET user from session despite someone is logged in: {err}"); None } } } /// Handles any route that is not defined explicitly. pub async fn index(id: Option, method: Method) -> impl Responder { match method { Method::GET => match id { Some(id) => HttpResponse::Ok() .content_type(ContentType::plaintext()) .body(format!( "You are logged in. Welcome! ({:?})", id.id().unwrap() )), None => HttpResponse::Unauthorized().body("Please log in to continue!"), }, _ => HttpResponse::Forbidden().finish(), } } /// Creates an Identity in the session if the provided credentials are valid. #[post("/login")] pub async fn post_login( req: HttpRequest, payload: web::Json, repo: web::Data, session: Session, ) -> impl Responder { log::debug!("Received {payload:?}"); match repo.read(&payload.id()) { Ok(Some(user)) => { if payload.salt() == "" { log::debug!("Initial login request with empty salt: {payload:?}"); HttpResponse::Ok().json(format!("{{ 'salt': '{}' }}", user.salt())) } else if payload.hash() == user.hash() { log::debug!("User successfully logged in: {payload:?} == {user:?}"); // TODO: Mayb handle more gracefully Identity::login(&req.extensions(), format!("{}", payload.id())) .expect("Log the user in"); // TODO: Mayb handle more gracefully session .insert("user", payload.0) .expect("Insert user into session"); HttpResponse::Ok().finish() } else { log::debug!("Wrong password hash for user: {payload:?} != {user:?}"); HttpResponse::Unauthorized().finish() } } Ok(None) => { log::debug!("User not found: {payload:?}"); HttpResponse::Unauthorized().finish() } Err(_) => { let msg = format!("Could not create user: {payload:?}"); log::debug!("{}", msg); HttpResponse::InternalServerError().body(msg) } } } /// Removes the current Identity from the session -> logs the user out. #[delete("/logout")] pub async fn delete_logout(id: Identity) -> impl Responder { id.logout(); HttpResponse::Ok() }