From 8d91543a13c753827f221acc700cc41e541cadf2 Mon Sep 17 00:00:00 2001 From: Nutomic Date: Thu, 12 Dec 2024 15:06:38 +0000 Subject: [PATCH] Allow admins to view deleted users (fixes #5249) (#5258) * Allow admins to view deleted users (fixes #5249) * remove check --- crates/api/src/community/ban.rs | 2 +- crates/api/src/local_user/ban_person.rs | 2 +- crates/api/src/local_user/block.rs | 2 +- crates/api_common/src/utils.rs | 2 -- crates/apub/src/api/read_person.rs | 8 +++-- crates/apub/src/api/resolve_object.rs | 2 +- crates/db_views_actor/src/community_view.rs | 4 +-- crates/db_views_actor/src/person_view.rs | 34 +++++++++++++-------- crates/utils/src/error.rs | 5 ++- 9 files changed, 36 insertions(+), 25 deletions(-) diff --git a/crates/api/src/community/ban.rs b/crates/api/src/community/ban.rs index 8689d2563..547838fa7 100644 --- a/crates/api/src/community/ban.rs +++ b/crates/api/src/community/ban.rs @@ -110,7 +110,7 @@ pub async fn ban_from_community( ModBanFromCommunity::create(&mut context.pool(), &form).await?; - let person_view = PersonView::read(&mut context.pool(), data.person_id).await?; + let person_view = PersonView::read(&mut context.pool(), data.person_id, false).await?; ActivityChannel::submit_activity( SendActivityData::BanFromCommunity { diff --git a/crates/api/src/local_user/ban_person.rs b/crates/api/src/local_user/ban_person.rs index f929433f0..715bd206d 100644 --- a/crates/api/src/local_user/ban_person.rs +++ b/crates/api/src/local_user/ban_person.rs @@ -88,7 +88,7 @@ pub async fn ban_from_site( ModBan::create(&mut context.pool(), &form).await?; - let person_view = PersonView::read(&mut context.pool(), person.id).await?; + let person_view = PersonView::read(&mut context.pool(), person.id, false).await?; ban_nonlocal_user_from_local_communities( &local_user_view, diff --git a/crates/api/src/local_user/block.rs b/crates/api/src/local_user/block.rs index 80532e897..3aee554d4 100644 --- a/crates/api/src/local_user/block.rs +++ b/crates/api/src/local_user/block.rs @@ -48,7 +48,7 @@ pub async fn user_block_person( .with_lemmy_type(LemmyErrorType::PersonBlockAlreadyExists)?; } - let person_view = PersonView::read(&mut context.pool(), target_id).await?; + let person_view = PersonView::read(&mut context.pool(), target_id, false).await?; Ok(Json(BlockPersonResponse { person_view, blocked: data.block, diff --git a/crates/api_common/src/utils.rs b/crates/api_common/src/utils.rs index 21154c823..80f559edb 100644 --- a/crates/api_common/src/utils.rs +++ b/crates/api_common/src/utils.rs @@ -123,8 +123,6 @@ pub fn is_admin(local_user_view: &LocalUserView) -> LemmyResult<()> { check_user_valid(&local_user_view.person)?; if !local_user_view.local_user.admin { Err(LemmyErrorType::NotAnAdmin)? - } else if local_user_view.person.banned { - Err(LemmyErrorType::Banned)? } else { Ok(()) } diff --git a/crates/apub/src/api/read_person.rs b/crates/apub/src/api/read_person.rs index fac68cd63..72dce8140 100644 --- a/crates/apub/src/api/read_person.rs +++ b/crates/apub/src/api/read_person.rs @@ -4,7 +4,7 @@ use actix_web::web::{Json, Query}; use lemmy_api_common::{ context::LemmyContext, person::{GetPersonDetails, GetPersonDetailsResponse}, - utils::{check_private_instance, read_site_for_actor}, + utils::{check_private_instance, is_admin, read_site_for_actor}, }; use lemmy_db_schema::{source::person::Person, utils::post_to_comment_sort_type}; use lemmy_db_views::{ @@ -45,7 +45,11 @@ pub async fn read_person( // You don't need to return settings for the user, since this comes back with GetSite // `my_user` - let person_view = PersonView::read(&mut context.pool(), person_details_id).await?; + let is_admin = local_user_view + .as_ref() + .map(|l| is_admin(l).is_ok()) + .unwrap_or_default(); + let person_view = PersonView::read(&mut context.pool(), person_details_id, is_admin).await?; let sort = data.sort; let page = data.page; diff --git a/crates/apub/src/api/resolve_object.rs b/crates/apub/src/api/resolve_object.rs index 04d489592..8d2cd384f 100644 --- a/crates/apub/src/api/resolve_object.rs +++ b/crates/apub/src/api/resolve_object.rs @@ -60,7 +60,7 @@ async fn convert_response( } }, SearchableObjects::PersonOrCommunity(pc) => match *pc { - UserOrCommunity::User(u) => res.person = Some(PersonView::read(pool, u.id).await?), + UserOrCommunity::User(u) => res.person = Some(PersonView::read(pool, u.id, is_admin).await?), UserOrCommunity::Community(c) => { res.community = Some(CommunityView::read(pool, c.id, local_user.as_ref(), is_admin).await?) } diff --git a/crates/db_views_actor/src/community_view.rs b/crates/db_views_actor/src/community_view.rs index f6ce82d37..8bcf50ba3 100644 --- a/crates/db_views_actor/src/community_view.rs +++ b/crates/db_views_actor/src/community_view.rs @@ -188,7 +188,7 @@ impl CommunityView { let is_mod = CommunityModeratorView::check_is_community_moderator(pool, community_id, person_id).await; if is_mod.is_ok() - || PersonView::read(pool, person_id) + || PersonView::read(pool, person_id, false) .await .is_ok_and(|t| t.is_admin) { @@ -206,7 +206,7 @@ impl CommunityView { let is_mod_of_any = CommunityModeratorView::is_community_moderator_of_any(pool, person_id).await; if is_mod_of_any.is_ok() - || PersonView::read(pool, person_id) + || PersonView::read(pool, person_id, false) .await .is_ok_and(|t| t.is_admin) { diff --git a/crates/db_views_actor/src/person_view.rs b/crates/db_views_actor/src/person_view.rs index 39d1ac27c..b90ab7811 100644 --- a/crates/db_views_actor/src/person_view.rs +++ b/crates/db_views_actor/src/person_view.rs @@ -58,12 +58,11 @@ fn post_to_person_sort_type(sort: PostSortType) -> PersonSortType { } fn queries<'a>( -) -> Queries, impl ListFn<'a, PersonView, ListMode>> { +) -> Queries, impl ListFn<'a, PersonView, ListMode>> { let all_joins = move |query: person::BoxedQuery<'a, Pg>| { query .inner_join(person_aggregates::table) .left_join(local_user::table) - .filter(person::deleted.eq(false)) .select(( person::all_columns, person_aggregates::all_columns, @@ -71,14 +70,17 @@ fn queries<'a>( )) }; - let read = move |mut conn: DbConn<'a>, person_id: PersonId| async move { - all_joins(person::table.find(person_id).into_boxed()) - .first(&mut conn) - .await + let read = move |mut conn: DbConn<'a>, params: (PersonId, bool)| async move { + let (person_id, is_admin) = params; + let mut query = all_joins(person::table.find(person_id).into_boxed()); + if !is_admin { + query = query.filter(person::deleted.eq(false)); + } + query.first(&mut conn).await }; let list = move |mut conn: DbConn<'a>, mode: ListMode| async move { - let mut query = all_joins(person::table.into_boxed()); + let mut query = all_joins(person::table.into_boxed()).filter(person::deleted.eq(false)); match mode { ListMode::Admins => { query = query @@ -135,8 +137,12 @@ fn queries<'a>( } impl PersonView { - pub async fn read(pool: &mut DbPool<'_>, person_id: PersonId) -> Result { - queries().read(pool, person_id).await + pub async fn read( + pool: &mut DbPool<'_>, + person_id: PersonId, + is_admin: bool, + ) -> Result { + queries().read(pool, (person_id, is_admin)).await } pub async fn admins(pool: &mut DbPool<'_>) -> Result, Error> { @@ -243,9 +249,13 @@ mod tests { ) .await?; - let read = PersonView::read(pool, data.alice.id).await; + let read = PersonView::read(pool, data.alice.id, false).await; assert!(read.is_err()); + // only admin can view deleted users + let read = PersonView::read(pool, data.alice.id, true).await; + assert!(read.is_ok()); + let list = PersonQuery { sort: Some(PostSortType::New), ..Default::default() @@ -303,10 +313,10 @@ mod tests { assert_length!(1, list); assert_eq!(list[0].person.id, data.alice.id); - let is_admin = PersonView::read(pool, data.alice.id).await?.is_admin; + let is_admin = PersonView::read(pool, data.alice.id, false).await?.is_admin; assert!(is_admin); - let is_admin = PersonView::read(pool, data.bob.id).await?.is_admin; + let is_admin = PersonView::read(pool, data.bob.id, false).await?.is_admin; assert!(!is_admin); cleanup(data, pool).await diff --git a/crates/utils/src/error.rs b/crates/utils/src/error.rs index f45bc271f..4f28aaa32 100644 --- a/crates/utils/src/error.rs +++ b/crates/utils/src/error.rs @@ -113,7 +113,6 @@ pub enum LemmyErrorType { SystemErrLogin, CouldntSetAllRegistrationsAccepted, CouldntSetAllEmailVerified, - Banned, BlockedUrl, CouldntGetComments, CouldntGetPosts, @@ -328,9 +327,9 @@ cfg_if! { #[test] fn deserializes_no_message() -> LemmyResult<()> { - let err = LemmyError::from(LemmyErrorType::Banned).error_response(); + let err = LemmyError::from(LemmyErrorType::BlockedUrl).error_response(); let json = String::from_utf8(err.into_body().try_into_bytes().unwrap_or_default().to_vec())?; - assert_eq!(&json, "{\"error\":\"banned\"}"); + assert_eq!(&json, "{\"error\":\"blocked_url\"}"); Ok(()) }