Skip to content
Clone
29cc961
145 lines 5.3 KB Rust
use models::users::user;
use models::users::{user_blocks, user_followers};
use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set};
use time::OffsetDateTime;
use uuid::Uuid;
use super::AuthService;
use crate::errors::AuthError;
use crate::share::types::UserPublic;
impl AuthService {
pub async fn public_user(&self, uid: Uuid) -> Result<UserPublic, AuthError> {
let Some(user) = user::Entity::find_by_id(uid).one(self.db().read()).await? else {
return Err(AuthError::NotFound);
};
Ok(UserPublic {
uid: user.uid,
username: user.username,
display_name: user.display_name,
avatar_url: user.avatar_url,
})
}
pub async fn follow(&self, follower_uid: Uuid, followed_uid: Uuid) -> Result<(), AuthError> {
if follower_uid == followed_uid {
return Err(AuthError::BadRequest(
"cannot follow yourself".to_string(),
));
}
let db = self.db();
let followed_exists = user::Entity::find_by_id(followed_uid).one(db.read()).await?;
if followed_exists.is_none() {
return Err(AuthError::NotFound);
}
let existing = user_followers::Entity::find()
.filter(user_followers::Column::FollowerId.eq(follower_uid))
.filter(user_followers::Column::FollowedId.eq(followed_uid))
.one(db.write())
.await?;
if existing.is_some() {
return Ok(());
}
let row = user_followers::ActiveModel {
id: Set(Uuid::now_v7()),
follower_id: Set(follower_uid),
followed_id: Set(followed_uid),
created_at: Set(OffsetDateTime::now_utc()),
};
row.insert(db.write()).await?;
Ok(())
}
pub async fn unfollow(&self, follower_uid: Uuid, followed_uid: Uuid) -> Result<(), AuthError> {
let db = self.db();
user_followers::Entity::delete_many()
.filter(user_followers::Column::FollowerId.eq(follower_uid))
.filter(user_followers::Column::FollowedId.eq(followed_uid))
.exec(db.write())
.await?;
Ok(())
}
pub async fn followers(&self, uid: Uuid) -> Result<Vec<UserPublic>, AuthError> {
let rows = user_followers::Entity::find()
.filter(user_followers::Column::FollowedId.eq(uid))
.all(self.db().read())
.await?;
let ids: Vec<Uuid> = rows.into_iter().map(|row| row.follower_id).collect();
self.load_users_public(&ids).await
}
pub async fn following(&self, uid: Uuid) -> Result<Vec<UserPublic>, AuthError> {
let rows = user_followers::Entity::find()
.filter(user_followers::Column::FollowerId.eq(uid))
.all(self.db().read())
.await?;
let ids: Vec<Uuid> = rows.into_iter().map(|row| row.followed_id).collect();
self.load_users_public(&ids).await
}
pub async fn block(&self, blocker_uid: Uuid, blocked_uid: Uuid) -> Result<(), AuthError> {
if blocker_uid == blocked_uid {
return Err(AuthError::BadRequest("cannot block yourself".to_string()));
}
let db = self.db();
let blocked_exists = user::Entity::find_by_id(blocked_uid).one(db.read()).await?;
if blocked_exists.is_none() {
return Err(AuthError::NotFound);
}
let existing = user_blocks::Entity::find()
.filter(user_blocks::Column::BlockerId.eq(blocker_uid))
.filter(user_blocks::Column::BlockedId.eq(blocked_uid))
.one(db.write())
.await?;
if existing.is_some() {
return Ok(());
}
let row = user_blocks::ActiveModel {
id: Set(Uuid::now_v7()),
blocker_id: Set(blocker_uid),
blocked_id: Set(blocked_uid),
created_at: Set(OffsetDateTime::now_utc()),
};
row.insert(db.write()).await?;
Ok(())
}
pub async fn unblock(&self, blocker_uid: Uuid, blocked_uid: Uuid) -> Result<(), AuthError> {
let db = self.db();
user_blocks::Entity::delete_many()
.filter(user_blocks::Column::BlockerId.eq(blocker_uid))
.filter(user_blocks::Column::BlockedId.eq(blocked_uid))
.exec(db.write())
.await?;
Ok(())
}
pub async fn blocked_users(&self, uid: Uuid) -> Result<Vec<UserPublic>, AuthError> {
let rows = user_blocks::Entity::find()
.filter(user_blocks::Column::BlockerId.eq(uid))
.all(self.db().read())
.await?;
let ids: Vec<Uuid> = rows.into_iter().map(|row| row.blocked_id).collect();
self.load_users_public(&ids).await
}
async fn load_users_public(&self, ids: &[Uuid]) -> Result<Vec<UserPublic>, AuthError> {
if ids.is_empty() {
return Ok(Vec::new());
}
let rows = user::Entity::find()
.filter(user::Column::Uid.is_in(ids.iter().copied()))
.all(self.db().read())
.await?;
Ok(rows
.into_iter()
.map(|user| UserPublic {
uid: user.uid,
username: user.username,
display_name: user.display_name,
avatar_url: user.avatar_url,
})
.collect())
}
}