gitdataai/libs/service/user/user_info.rs
2026-04-14 19:02:01 +08:00

110 lines
3.7 KiB
Rust

use crate::AppService;
use crate::error::AppError;
use chrono::{DateTime, Utc};
use sea_orm::*;
use serde::{Deserialize, Serialize};
use session::Session;
use utoipa::ToSchema;
use uuid::Uuid;
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
pub struct UserInfoExternal {
pub user_uid: Uuid,
pub username: String,
pub display_name: String,
pub avatar_url: Option<String>,
pub master_email: Option<String>,
pub timezone: String,
pub language: String,
pub website_url: Option<String>,
pub organization: Option<String>,
pub last_sign_in_at: Option<DateTime<Utc>>,
pub is_owner: bool,
pub is_subscribe: bool,
pub total_projects: u64,
pub total_repos: u64,
}
impl AppService {
pub async fn user_info(
&self,
context: Session,
username: String,
) -> Result<UserInfoExternal, AppError> {
let user = models::users::user::Entity::find()
.filter(models::users::user::Column::Username.eq(&username))
.one(&self.db)
.await?
.ok_or(AppError::UserNotFound)?;
let preferences = models::users::user_preferences::Entity::find()
.filter(models::users::user_preferences::Column::User.eq(user.uid))
.one(&self.db)
.await?;
let master_email = models::users::user_email::Entity::find()
.filter(models::users::user_email::Column::User.eq(user.uid))
.one(&self.db)
.await?
.map(|email| email.email);
let is_subscribe = if let Some(current_uid) = context.user() {
let relation = models::users::user_relation::Entity::find()
.filter(models::users::user_relation::Column::User.eq(current_uid))
.filter(models::users::user_relation::Column::Target.eq(user.uid))
.filter(models::users::user_relation::Column::RelationType.eq("follow"))
.one(&self.db)
.await?;
relation.is_some()
} else {
false
};
// Get user's project memberships to find repos
let user_project_ids: Vec<uuid::Uuid> = models::projects::project_members::Entity::find()
.filter(models::projects::project_members::Column::User.eq(user.uid))
.select_only()
.column(models::projects::project_members::Column::Project)
.into_tuple::<uuid::Uuid>()
.all(&self.db)
.await?;
// Count projects created by user
let total_projects = models::projects::project::Entity::find()
.filter(models::projects::project::Column::CreatedBy.eq(user.uid))
.count(&self.db)
.await?;
// Count repos in user's projects
let total_repos = models::repos::repo::Entity::find()
.filter(models::repos::repo::Column::Project.is_in(user_project_ids))
.count(&self.db)
.await?;
Ok(UserInfoExternal {
user_uid: user.uid,
username: user.username,
display_name: user.display_name.unwrap_or_default(),
avatar_url: user.avatar_url,
master_email,
timezone: preferences
.as_ref()
.map(|p| p.timezone.clone())
.unwrap_or_else(|| "UTC".to_string()),
language: preferences
.as_ref()
.map(|p| p.language.clone())
.unwrap_or_else(|| "en".to_string()),
website_url: user.website_url,
organization: user.organization,
last_sign_in_at: user.last_sign_in_at,
is_owner: context.user().map(|u| u == user.uid).unwrap_or(false),
is_subscribe,
total_projects,
total_repos,
})
}
}