//! # User controller //! //! The actions of the user on his account when he is authenticated. use crate::constants::StaticConstraints; use crate::controllers::HttpResult; use crate::models::User; use crate::services::login_token_service::LoginToken; use crate::services::rate_limiter_service::RatedAction; use crate::services::{rate_limiter_service, users_service}; use actix_remote_ip::RemoteIP; use actix_web::web::Json; use actix_web::HttpResponse; #[derive(serde::Serialize)] struct UserAPI<'a> { #[serde(flatten)] user: &'a User, has_password: bool, } /// Get account information pub async fn auth_info(token: LoginToken) -> HttpResult { let user = users_service::get_by_id(token.user_id).await?; Ok(HttpResponse::Ok().json(UserAPI { user: &user, has_password: user .password .as_deref() .map(|p| !p.is_empty()) .unwrap_or_default(), })) } #[derive(serde::Deserialize)] pub struct ProfileUpdateQuery { name: String, } /// Update profile information pub async fn update_profile(token: LoginToken, profile: Json) -> HttpResult { if !StaticConstraints::default() .user_name_len .validate(&profile.name) { return Ok(HttpResponse::BadRequest().json("Nom invalide!")); } let mut user = users_service::get_by_id(token.user_id).await?; user.name = profile.0.name; users_service::update_account(user).await?; Ok(HttpResponse::Accepted().finish()) } #[derive(serde::Deserialize)] pub struct ReplacePasswordQuery { old_password: String, new_password: String, } /// Replace user password pub async fn replace_password( remote_ip: RemoteIP, token: LoginToken, q: Json, ) -> HttpResult { // Rate limiting if rate_limiter_service::should_block_action( remote_ip.0, RatedAction::RequestReplacePasswordSignedIn, ) .await? { return Ok(HttpResponse::TooManyRequests().finish()); } if !StaticConstraints::default() .password_len .validate(&q.new_password) { return Ok(HttpResponse::BadRequest().json("Nouveau mot de passe invalide!")); } let user = users_service::get_by_id(token.user_id).await?; if !user.check_password(&q.old_password) { rate_limiter_service::record_action( remote_ip.0, RatedAction::RequestReplacePasswordSignedIn, ) .await?; return Ok(HttpResponse::BadRequest().json("Ancien mot de passe invalide !")); } users_service::change_password(&user, &q.new_password).await?; Ok(HttpResponse::Accepted().finish()) }