gitdataai/libs/service/user/profile.rs
2026-04-15 09:08:09 +08:00

119 lines
3.9 KiB
Rust

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<String>,
pub website_url: Option<String>,
pub organization: Option<String>,
}
#[derive(Deserialize, Serialize, Clone, Debug, utoipa::ToSchema)]
pub struct ProfileResponse {
pub uid: Uuid,
pub username: String,
pub display_name: Option<String>,
pub avatar_url: Option<String>,
pub website_url: Option<String>,
pub organization: Option<String>,
pub created_at: chrono::DateTime<Utc>,
pub updated_at: chrono::DateTime<Utc>,
pub last_sign_in_at: Option<chrono::DateTime<Utc>>,
}
impl From<user::Model> 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<ProfileResponse, AppError> {
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<ProfileResponse, AppError> {
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<ProfileResponse, AppError> {
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<ProfileResponse, AppError> {
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<ProfileResponse, AppError> {
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))
}
}