use sea_orm::prelude::Uuid; use sea_orm::{ ActiveModelTrait, ColumnTrait, DbConn, DbErr, EntityTrait, JoinType, QueryFilter, QueryOrder, QuerySelect, RelationTrait, Set, TransactionTrait, }; use models::domains::{top_friends, user}; use models::params::user::{CreateUserParams, UpdateUserParams}; use models::queries::user::UserQuery; use crate::error::UserError; use crate::persistence::follow::{get_follower_ids, get_following_ids}; pub async fn create_user( db: &DbConn, params: CreateUserParams, ) -> Result { user::ActiveModel { username: Set(params.username), ..Default::default() } .save(db) .await } pub async fn search_users(db: &DbConn, query: UserQuery) -> Result, DbErr> { user::Entity::find() .filter(user::Column::Username.contains(query.username.unwrap_or_default())) .all(db) .await } pub async fn get_user(db: &DbConn, id: Uuid) -> Result, DbErr> { user::Entity::find_by_id(id).one(db).await } pub async fn get_user_by_username( db: &DbConn, username: &str, ) -> Result, DbErr> { user::Entity::find() .filter(user::Column::Username.eq(username)) .one(db) .await } pub async fn get_users_by_ids(db: &DbConn, ids: Vec) -> Result, DbErr> { user::Entity::find() .filter(user::Column::Id.is_in(ids)) .all(db) .await } pub async fn update_user_profile( db: &DbConn, user_id: Uuid, params: UpdateUserParams, ) -> Result { let mut user: user::ActiveModel = get_user(db, user_id) .await .map_err(|e| UserError::Internal(e.to_string()))? .ok_or(UserError::NotFound)? .into(); if let Some(display_name) = params.display_name { user.display_name = Set(Some(display_name)); } if let Some(bio) = params.bio { user.bio = Set(Some(bio)); } if let Some(avatar_url) = params.avatar_url { user.avatar_url = Set(Some(avatar_url)); } if let Some(header_url) = params.header_url { user.header_url = Set(Some(header_url)); } if let Some(custom_css) = params.custom_css { user.custom_css = Set(Some(custom_css)); } if let Some(friend_usernames) = params.top_friends { let txn = db .begin() .await .map_err(|e| UserError::Internal(e.to_string()))?; top_friends::Entity::delete_many() .filter(top_friends::Column::UserId.eq(user_id)) .exec(&txn) .await .map_err(|e| UserError::Internal(e.to_string()))?; let friends = user::Entity::find() .filter(user::Column::Username.is_in(friend_usernames.clone())) .all(&txn) .await .map_err(|e| UserError::Internal(e.to_string()))?; if friends.len() != friend_usernames.len() { return Err(UserError::Validation( "One or more usernames in top_friends do not exist".to_string(), )); } let new_top_friends: Vec = friends .iter() .enumerate() .map(|(index, friend)| top_friends::ActiveModel { user_id: Set(user_id), friend_id: Set(friend.id), position: Set((index + 1) as i16), ..Default::default() }) .collect(); if !new_top_friends.is_empty() { top_friends::Entity::insert_many(new_top_friends) .exec(&txn) .await .map_err(|e| UserError::Internal(e.to_string()))?; } txn.commit() .await .map_err(|e| UserError::Internal(e.to_string()))?; } user.update(db) .await .map_err(|e| UserError::Internal(e.to_string())) } pub async fn get_top_friends(db: &DbConn, user_id: Uuid) -> Result, DbErr> { user::Entity::find() .join( JoinType::InnerJoin, top_friends::Relation::Friend.def().rev(), ) .filter(top_friends::Column::UserId.eq(user_id)) .order_by_asc(top_friends::Column::Position) .all(db) .await } pub async fn get_following(db: &DbConn, user_id: Uuid) -> Result, DbErr> { let following_ids = get_following_ids(db, user_id).await?; if following_ids.is_empty() { return Ok(vec![]); } get_users_by_ids(db, following_ids).await } pub async fn get_followers(db: &DbConn, user_id: Uuid) -> Result, DbErr> { let follower_ids = get_follower_ids(db, user_id).await?; if follower_ids.is_empty() { return Ok(vec![]); } get_users_by_ids(db, follower_ids).await }