gitdataai/lib/service/users/public.rs
2026-05-30 01:38:40 +08:00

73 lines
2.5 KiB
Rust

use db::sqlx;
use model::users::{UserPrivacyModel, UserProfileModel};
use serde::{Deserialize, Serialize};
use crate::{AppService, error::AppError};
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct PublicUserResponse {
pub username: String,
pub display_name: String,
pub avatar_url: String,
pub website_url: String,
pub language: String,
pub timezone: String,
pub allow_direct_messages: bool,
pub show_online_status: bool,
}
impl AppService {
pub async fn users_public_by_username(
&self,
username: &str,
) -> Result<PublicUserResponse, AppError> {
let user = self.users_find_active_user_by_username(username).await?;
let privacy = sqlx::query_as::<_, UserPrivacyModel>(
"SELECT \"user\", profile_visibility, email_visibility, activity_visibility, allow_search_indexing, allow_direct_messages, show_online_status, created_at, updated_at \
FROM user_privacy WHERE \"user\" = $1",
)
.bind(user.id)
.fetch_optional(self.db.reader())
.await
.map_err(|e| AppError::DatabaseError(e.to_string()))?;
if privacy
.as_ref()
.is_some_and(|privacy| privacy.profile_visibility == "private")
{
return Err(AppError::Forbidden("profile is private".to_string()));
}
let profile = sqlx::query_as::<_, UserProfileModel>(
"SELECT \"user\", language, theme, timezone, created_at, updated_at \
FROM user_profile WHERE \"user\" = $1",
)
.bind(user.id)
.fetch_optional(self.db.reader())
.await
.map_err(|e| AppError::DatabaseError(e.to_string()))?;
Ok(PublicUserResponse {
username: user.username,
display_name: user.display_name,
avatar_url: user.avatar_url,
website_url: user.website_url,
language: profile
.as_ref()
.map(|profile| profile.language.clone())
.unwrap_or_else(|| "en".to_string()),
timezone: profile
.map(|profile| profile.timezone)
.unwrap_or_else(|| "UTC".to_string()),
allow_direct_messages: privacy
.as_ref()
.map(|privacy| privacy.allow_direct_messages)
.unwrap_or(true),
show_online_status: privacy
.map(|privacy| privacy.show_online_status)
.unwrap_or(true),
})
}
}