feat(labrinth): user blocking (#6837)

* feat(labrinth): user blocking

still wip, nothing is hooked up

* style(labrinth): cargo fmt

* refactor(labrinth): move block/unblock routes to public api

* feat(labrinth): block friend requests if blocked

* feat(labrinth): remove friend/request on block

* feat(labrinth): get blocked users endpoint
This commit is contained in:
Sychic
2026-07-27 19:41:57 +00:00
committed by GitHub
parent 224c28f29d
commit ebc7cac8b0
12 changed files with 358 additions and 0 deletions
@@ -0,0 +1,121 @@
use crate::auth::get_user_from_headers;
use crate::database::PgPool;
use crate::database::models::DBUser;
use crate::database::models::blocked_user_item::DBBlockedUser;
use crate::database::models::friend_item::DBFriend;
use crate::models::pats::Scopes;
use crate::queue::session::AuthQueue;
use crate::routes::ApiError;
use actix_web::{HttpRequest, delete, get, post, web};
use ariadne::ids::UserId;
use eyre::eyre;
use xredis::RedisPool;
pub fn config(cfg: &mut actix_web::web::ServiceConfig) {
cfg.service(block_user);
cfg.service(unblock_user);
cfg.service(get_blocked_users);
}
/// Block a user.
#[utoipa::path(tag = "blocked_users", responses((status = NO_CONTENT)))]
#[post("/block/{id}")]
pub async fn block_user(
req: HttpRequest,
info: web::Path<(String,)>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<(), ApiError> {
let user = get_user_from_headers(
&req,
&**pool,
&redis,
&session_queue,
Scopes::USER_WRITE,
)
.await?
.1;
let user_id = info.into_inner().0;
let Some(blocked) = DBUser::get(&user_id, &**pool, &redis).await? else {
return Err(ApiError::NotFound);
};
if blocked.id == user.id.into() {
return Err(ApiError::Request(eyre!("you cannot block yourself")));
}
let mut transaction = pool.begin().await?;
DBFriend::remove(user.id.into(), blocked.id, &mut transaction).await?;
DBBlockedUser {
user_id: user.id.into(),
blocked_id: blocked.id,
}
.insert(&mut transaction)
.await?;
transaction.commit().await?;
Ok(())
}
/// Unblock a user.
#[utoipa::path(tag = "blocked_users", responses((status = NO_CONTENT)))]
#[delete("/block/{id}")]
pub async fn unblock_user(
req: HttpRequest,
info: web::Path<(String,)>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<(), ApiError> {
let user = get_user_from_headers(
&req,
&**pool,
&redis,
&session_queue,
Scopes::USER_WRITE,
)
.await?
.1;
let user_id = info.into_inner().0;
let Some(blocked) = DBUser::get(&user_id, &**pool, &redis).await? else {
return Err(ApiError::NotFound);
};
DBBlockedUser::remove(user.id.into(), blocked.id, &**pool).await?;
Ok(())
}
/// List the users blocked by the current user.
#[utoipa::path(tag = "blocked_users", responses((status = OK, body = Vec<UserId>)))]
#[get("/blocks")]
pub async fn get_blocked_users(
req: HttpRequest,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<web::Json<Vec<UserId>>, ApiError> {
let user = get_user_from_headers(
&req,
&**pool,
&redis,
&session_queue,
Scopes::USER_READ,
)
.await?
.1;
let blocked = DBBlockedUser::get_blocked_for_user(user.id.into(), &**pool)
.await?
.into_iter()
.map(UserId::from)
.collect();
Ok(web::Json(blocked))
}
+13
View File
@@ -1,5 +1,6 @@
use crate::auth::get_user_from_headers;
use crate::database::PgPool;
use crate::database::models::blocked_user_item::DBBlockedUser;
use crate::database::models::friend_item::DBFriend;
use crate::database::models::{DBUser, DBUserId};
use crate::models::pats::Scopes;
@@ -49,6 +50,18 @@ pub async fn add_friend(
return Err(ApiError::NotFound);
};
if DBBlockedUser::is_blocked(friend.id, user.id.into(), &**pool).await? {
return Err(ApiError::InvalidInput(
"You've been blocked the other user!".to_string(),
));
} else if DBBlockedUser::is_blocked(user.id.into(), friend.id, &**pool)
.await?
{
return Err(ApiError::InvalidInput(
"You've blocked the other user!".to_string(),
));
}
let mut transaction = pool.begin().await?;
if let Some(friend) =
+5
View File
@@ -6,6 +6,7 @@ use serde_json::json;
pub mod analytics_event;
pub mod analytics_get;
pub mod blocked_users;
pub mod collections;
pub mod content;
pub mod friends;
@@ -66,6 +67,7 @@ pub fn config(cfg: &mut web::ServiceConfig) {
.configure(version_file::config)
.configure(versions::config)
.configure(friends::config)
.configure(blocked_users::config)
.configure(content::config),
);
}
@@ -227,6 +229,9 @@ pub fn config(cfg: &mut web::ServiceConfig) {
friends::add_friend,
friends::remove_friend,
friends::friends,
blocked_users::block_user,
blocked_users::unblock_user,
blocked_users::get_blocked_users,
content::resolve_content,
),
modifiers(&V3PathModifier, &SecurityAddon)