use crate::AppService; use crate::error::AppError; use chrono::Utc; use models::users::{user, user_activity_log}; use sea_orm::*; use serde::{Deserialize, Serialize}; use session::Session; use uuid::Uuid; #[derive(Deserialize, Serialize, Clone, Debug, utoipa::ToSchema)] pub struct UpdateProfileParams { pub avatar_url: Option, pub website_url: Option, pub organization: Option, } #[derive(Deserialize, Serialize, Clone, Debug, utoipa::ToSchema)] pub struct ProfileResponse { pub uid: Uuid, pub username: String, pub display_name: Option, pub avatar_url: Option, pub website_url: Option, pub organization: Option, pub created_at: chrono::DateTime, pub updated_at: chrono::DateTime, pub last_sign_in_at: Option>, } impl From for ProfileResponse { fn from(user: user::Model) -> Self { ProfileResponse { uid: user.uid, username: user.username, display_name: user.display_name, avatar_url: user.avatar_url, website_url: user.website_url, organization: user.organization, created_at: user.created_at, updated_at: user.updated_at, last_sign_in_at: user.last_sign_in_at, } } } impl AppService { pub async fn user_get_profile(&self, user_uid: Uuid) -> Result { let user = self.utils_find_user_by_uid(user_uid).await?; Ok(ProfileResponse::from(user)) } pub async fn user_get_profile_by_username( &self, user_name: String, ) -> Result { let user = self.utils_find_user_by_username(user_name).await?; Ok(ProfileResponse::from(user)) } pub async fn user_get_profile_by_context( &self, context: &Session, ) -> Result { let user_uid = context.user().ok_or(AppError::Unauthorized)?; let user = self.utils_find_user_by_uid(user_uid).await?; Ok(ProfileResponse::from(user)) } pub async fn user_get_current_profile( &self, context: &Session, ) -> Result { let user_uid = context.user().ok_or(AppError::Unauthorized)?; self.user_get_profile(user_uid).await } pub async fn user_update_profile( &self, context: &Session, params: UpdateProfileParams, ) -> Result { let user_uid = context.user().ok_or(AppError::Unauthorized)?; let user: user::Model = self.utils_find_user_by_uid(user_uid).await?; let mut active_user: user::ActiveModel = user.into(); if params.avatar_url.is_some() { active_user.avatar_url = Set(params.avatar_url.clone()); } if params.website_url.is_some() { active_user.website_url = Set(params.website_url.clone()); } if params.organization.is_some() { active_user.organization = Set(params.organization.clone()); } active_user.updated_at = Set(Utc::now()); let updated_user = active_user.update(&self.db).await?; let _ = user_activity_log::ActiveModel { user_uid: Set(Some(user_uid)), action: Set("profile_update".to_string()), ip_address: Set(context.ip_address()), user_agent: Set(context.user_agent()), details: Set(serde_json::json!({ "updated_fields": { "avatar_url": params.avatar_url.is_some(), "website_url": params.website_url.is_some(), "organization": params.organization.is_some(), } })), created_at: Set(Utc::now()), ..Default::default() } .insert(&self.db) .await; Ok(ProfileResponse::from(updated_user)) } }