110 lines
3.7 KiB
Rust
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,
|
|
})
|
|
}
|
|
}
|