You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
3.1 KiB

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<User> {
match session.get::<User>("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<Identity>, 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<User>,
repo: web::Data<UserRepository>,
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()
}