Allow admins to view deleted users (fixes #5249) (#5258)

* Allow admins to view deleted users (fixes #5249)

* remove check
This commit is contained in:
Nutomic 2024-12-12 15:06:38 +00:00 committed by GitHub
parent 6a9f924d20
commit 8d91543a13
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 36 additions and 25 deletions

View file

@ -110,7 +110,7 @@ pub async fn ban_from_community(
ModBanFromCommunity::create(&mut context.pool(), &form).await?; 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( ActivityChannel::submit_activity(
SendActivityData::BanFromCommunity { SendActivityData::BanFromCommunity {

View file

@ -88,7 +88,7 @@ pub async fn ban_from_site(
ModBan::create(&mut context.pool(), &form).await?; 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( ban_nonlocal_user_from_local_communities(
&local_user_view, &local_user_view,

View file

@ -48,7 +48,7 @@ pub async fn user_block_person(
.with_lemmy_type(LemmyErrorType::PersonBlockAlreadyExists)?; .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 { Ok(Json(BlockPersonResponse {
person_view, person_view,
blocked: data.block, blocked: data.block,

View file

@ -123,8 +123,6 @@ pub fn is_admin(local_user_view: &LocalUserView) -> LemmyResult<()> {
check_user_valid(&local_user_view.person)?; check_user_valid(&local_user_view.person)?;
if !local_user_view.local_user.admin { if !local_user_view.local_user.admin {
Err(LemmyErrorType::NotAnAdmin)? Err(LemmyErrorType::NotAnAdmin)?
} else if local_user_view.person.banned {
Err(LemmyErrorType::Banned)?
} else { } else {
Ok(()) Ok(())
} }

View file

@ -4,7 +4,7 @@ use actix_web::web::{Json, Query};
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
person::{GetPersonDetails, GetPersonDetailsResponse}, 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_schema::{source::person::Person, utils::post_to_comment_sort_type};
use lemmy_db_views::{ 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 // You don't need to return settings for the user, since this comes back with GetSite
// `my_user` // `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 sort = data.sort;
let page = data.page; let page = data.page;

View file

@ -60,7 +60,7 @@ async fn convert_response(
} }
}, },
SearchableObjects::PersonOrCommunity(pc) => match *pc { 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) => { UserOrCommunity::Community(c) => {
res.community = Some(CommunityView::read(pool, c.id, local_user.as_ref(), is_admin).await?) res.community = Some(CommunityView::read(pool, c.id, local_user.as_ref(), is_admin).await?)
} }

View file

@ -188,7 +188,7 @@ impl CommunityView {
let is_mod = let is_mod =
CommunityModeratorView::check_is_community_moderator(pool, community_id, person_id).await; CommunityModeratorView::check_is_community_moderator(pool, community_id, person_id).await;
if is_mod.is_ok() if is_mod.is_ok()
|| PersonView::read(pool, person_id) || PersonView::read(pool, person_id, false)
.await .await
.is_ok_and(|t| t.is_admin) .is_ok_and(|t| t.is_admin)
{ {
@ -206,7 +206,7 @@ impl CommunityView {
let is_mod_of_any = let is_mod_of_any =
CommunityModeratorView::is_community_moderator_of_any(pool, person_id).await; CommunityModeratorView::is_community_moderator_of_any(pool, person_id).await;
if is_mod_of_any.is_ok() if is_mod_of_any.is_ok()
|| PersonView::read(pool, person_id) || PersonView::read(pool, person_id, false)
.await .await
.is_ok_and(|t| t.is_admin) .is_ok_and(|t| t.is_admin)
{ {

View file

@ -58,12 +58,11 @@ fn post_to_person_sort_type(sort: PostSortType) -> PersonSortType {
} }
fn queries<'a>( fn queries<'a>(
) -> Queries<impl ReadFn<'a, PersonView, PersonId>, impl ListFn<'a, PersonView, ListMode>> { ) -> Queries<impl ReadFn<'a, PersonView, (PersonId, bool)>, impl ListFn<'a, PersonView, ListMode>> {
let all_joins = move |query: person::BoxedQuery<'a, Pg>| { let all_joins = move |query: person::BoxedQuery<'a, Pg>| {
query query
.inner_join(person_aggregates::table) .inner_join(person_aggregates::table)
.left_join(local_user::table) .left_join(local_user::table)
.filter(person::deleted.eq(false))
.select(( .select((
person::all_columns, person::all_columns,
person_aggregates::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 { let read = move |mut conn: DbConn<'a>, params: (PersonId, bool)| async move {
all_joins(person::table.find(person_id).into_boxed()) let (person_id, is_admin) = params;
.first(&mut conn) let mut query = all_joins(person::table.find(person_id).into_boxed());
.await 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 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 { match mode {
ListMode::Admins => { ListMode::Admins => {
query = query query = query
@ -135,8 +137,12 @@ fn queries<'a>(
} }
impl PersonView { impl PersonView {
pub async fn read(pool: &mut DbPool<'_>, person_id: PersonId) -> Result<Self, Error> { pub async fn read(
queries().read(pool, person_id).await pool: &mut DbPool<'_>,
person_id: PersonId,
is_admin: bool,
) -> Result<Self, Error> {
queries().read(pool, (person_id, is_admin)).await
} }
pub async fn admins(pool: &mut DbPool<'_>) -> Result<Vec<Self>, Error> { pub async fn admins(pool: &mut DbPool<'_>) -> Result<Vec<Self>, Error> {
@ -243,9 +249,13 @@ mod tests {
) )
.await?; .await?;
let read = PersonView::read(pool, data.alice.id).await; let read = PersonView::read(pool, data.alice.id, false).await;
assert!(read.is_err()); 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 { let list = PersonQuery {
sort: Some(PostSortType::New), sort: Some(PostSortType::New),
..Default::default() ..Default::default()
@ -303,10 +313,10 @@ mod tests {
assert_length!(1, list); assert_length!(1, list);
assert_eq!(list[0].person.id, data.alice.id); 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); 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); assert!(!is_admin);
cleanup(data, pool).await cleanup(data, pool).await

View file

@ -113,7 +113,6 @@ pub enum LemmyErrorType {
SystemErrLogin, SystemErrLogin,
CouldntSetAllRegistrationsAccepted, CouldntSetAllRegistrationsAccepted,
CouldntSetAllEmailVerified, CouldntSetAllEmailVerified,
Banned,
BlockedUrl, BlockedUrl,
CouldntGetComments, CouldntGetComments,
CouldntGetPosts, CouldntGetPosts,
@ -328,9 +327,9 @@ cfg_if! {
#[test] #[test]
fn deserializes_no_message() -> LemmyResult<()> { 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())?; 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(()) Ok(())
} }