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
94 lines
3.1 KiB
2 years ago
|
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()
|
||
|
}
|