* Show deleted and removed posts for profile views. Fixes #2624 * Only showing non-deleted/removed posts for creator. * Add a admin or mod check to views, to show deleted and removed posts. - Also removed the pointless "blanking" functions * Fix clippy * Make hidden posts comment clearer. * Fixing federation tests. * Fixing fmt.
This commit is contained in:
parent
d9e7f0100a
commit
48f187188b
30 changed files with 215 additions and 243 deletions
|
@ -120,7 +120,6 @@ test("Delete a comment", async () => {
|
|||
commentRes.comment_view.comment.id
|
||||
);
|
||||
expect(deleteCommentRes.comment_view.comment.deleted).toBe(true);
|
||||
expect(deleteCommentRes.comment_view.comment.content).toBe("");
|
||||
|
||||
// Make sure that comment is undefined on beta
|
||||
let betaCommentRes = (await resolveComment(
|
||||
|
@ -159,7 +158,6 @@ test("Remove a comment from admin and community on the same instance", async ()
|
|||
// The beta admin removes it (the community lives on beta)
|
||||
let removeCommentRes = await removeComment(beta, true, betaCommentId);
|
||||
expect(removeCommentRes.comment_view.comment.removed).toBe(true);
|
||||
expect(removeCommentRes.comment_view.comment.content).toBe("");
|
||||
|
||||
// Make sure that comment is removed on alpha (it gets pushed since an admin from beta removed it)
|
||||
let refetchedPostComments = await getComments(
|
||||
|
|
|
@ -388,7 +388,7 @@ test("Enforce site ban for federated user", async () => {
|
|||
|
||||
// existing alpha post should be removed on beta
|
||||
let searchBeta2 = await searchPostLocal(beta, postRes1.post_view.post);
|
||||
expect(searchBeta2.posts[0]).toBeUndefined();
|
||||
expect(searchBeta2.posts[0].post.removed).toBe(true);
|
||||
|
||||
// Unban alpha
|
||||
let unBanAlpha = await banPersonFromSite(
|
||||
|
@ -436,7 +436,7 @@ test("Enforce community ban for federated user", async () => {
|
|||
|
||||
// ensure that the post by alpha got removed
|
||||
let searchAlpha1 = await searchPostLocal(alpha, postRes1.post_view.post);
|
||||
expect(searchAlpha1.posts[0]).toBeUndefined();
|
||||
expect(searchAlpha1.posts[0].post.removed).toBe(true);
|
||||
|
||||
// Alpha tries to make post on beta, but it fails because of ban
|
||||
let postRes2 = await createPost(alpha, betaCommunity.community.id);
|
||||
|
|
|
@ -64,7 +64,6 @@ test("Delete a private message", async () => {
|
|||
pmRes.private_message_view.private_message.id
|
||||
);
|
||||
expect(deletedPmRes.private_message_view.private_message.deleted).toBe(true);
|
||||
expect(deletedPmRes.private_message_view.private_message.content).toBe("");
|
||||
|
||||
// The GetPrivateMessages filters out deleted,
|
||||
// even though they are in the actual database.
|
||||
|
|
|
@ -2363,10 +2363,10 @@ kleur@^3.0.3:
|
|||
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
|
||||
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
|
||||
|
||||
lemmy-js-client@0.17.0-rc.61:
|
||||
version "0.17.0-rc.61"
|
||||
resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.17.0-rc.61.tgz#c01e129a3d4c3483ecf337f1e4acf0ad91f9684f"
|
||||
integrity sha512-xauBCD5i4vlUEWqsTMIXLCXeIjAK7ivVIN3C/g+RMAM7mD3CTcRkDZUerwnvLipIfr7V/4iYLWZW0orBaiV1CQ==
|
||||
lemmy-js-client@0.17.2-rc.1:
|
||||
version "0.17.2-rc.1"
|
||||
resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.17.2-rc.1.tgz#fe8d1508311bbf245acc98c2c3e47e2165a95b14"
|
||||
integrity sha512-YrOXuCofgkqp28krmPTQZAfUWL5zEDA0sRJ0abKcgf/I8YYkYkUkPS9TOORN5Lv3bc8RAAz4+2/zLHqYL/Tnow==
|
||||
dependencies:
|
||||
node-fetch "2.6.6"
|
||||
|
||||
|
|
|
@ -57,7 +57,8 @@ impl Perform for BlockCommunity {
|
|||
.map_err(|e| LemmyError::from_error_message(e, "community_block_already_exists"))?;
|
||||
}
|
||||
|
||||
let community_view = CommunityView::read(context.pool(), community_id, Some(person_id)).await?;
|
||||
let community_view =
|
||||
CommunityView::read(context.pool(), community_id, Some(person_id), None).await?;
|
||||
|
||||
Ok(BlockCommunityResponse {
|
||||
blocked: data.block,
|
||||
|
|
|
@ -53,7 +53,8 @@ impl Perform for FollowCommunity {
|
|||
|
||||
let community_id = data.community_id;
|
||||
let person_id = local_user_view.person.id;
|
||||
let community_view = CommunityView::read(context.pool(), community_id, Some(person_id)).await?;
|
||||
let community_view =
|
||||
CommunityView::read(context.pool(), community_id, Some(person_id), None).await?;
|
||||
let discussion_languages = CommunityLanguage::read(context.pool(), community_id).await?;
|
||||
|
||||
Ok(Self::Response {
|
||||
|
|
|
@ -83,7 +83,7 @@ impl Perform for TransferCommunity {
|
|||
|
||||
let community_id = data.community_id;
|
||||
let person_id = local_user_view.person.id;
|
||||
let community_view = CommunityView::read(context.pool(), community_id, Some(person_id))
|
||||
let community_view = CommunityView::read(context.pool(), community_id, Some(person_id), None)
|
||||
.await
|
||||
.map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ impl Perform for MarkPostAsRead {
|
|||
}
|
||||
|
||||
// Fetch it
|
||||
let post_view = PostView::read(context.pool(), post_id, Some(person_id)).await?;
|
||||
let post_view = PostView::read(context.pool(), post_id, Some(person_id), None).await?;
|
||||
|
||||
let res = Self::Response { post_view };
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ impl Perform for SavePost {
|
|||
|
||||
let post_id = data.post_id;
|
||||
let person_id = local_user_view.person.id;
|
||||
let post_view = PostView::read(context.pool(), post_id, Some(person_id)).await?;
|
||||
let post_view = PostView::read(context.pool(), post_id, Some(person_id), None).await?;
|
||||
|
||||
// Mark the post as read
|
||||
mark_post_as_read(person_id, post_id, context.pool()).await?;
|
||||
|
|
|
@ -37,7 +37,7 @@ impl Perform for CreatePostReport {
|
|||
|
||||
let person_id = local_user_view.person.id;
|
||||
let post_id = data.post_id;
|
||||
let post_view = PostView::read(context.pool(), post_id, None).await?;
|
||||
let post_view = PostView::read(context.pool(), post_id, None, None).await?;
|
||||
|
||||
check_community_ban(person_id, post_view.community.id, context.pool()).await?;
|
||||
|
||||
|
|
|
@ -61,6 +61,23 @@ pub async fn is_mod_or_admin(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn is_mod_or_admin_opt(
|
||||
pool: &DbPool,
|
||||
local_user_view: Option<&LocalUserView>,
|
||||
community_id: Option<CommunityId>,
|
||||
) -> Result<(), LemmyError> {
|
||||
if let Some(local_user_view) = local_user_view {
|
||||
if let Some(community_id) = community_id {
|
||||
is_mod_or_admin(pool, local_user_view.person.id, community_id).await
|
||||
} else {
|
||||
is_admin(local_user_view)
|
||||
}
|
||||
} else {
|
||||
Err(LemmyError::from_message("not_a_mod_or_admin"))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn is_top_admin(pool: &DbPool, person_id: PersonId) -> Result<(), LemmyError> {
|
||||
let admins = PersonViewSafe::admins(pool).await?;
|
||||
let top_admin = admins
|
||||
|
|
|
@ -17,7 +17,7 @@ use lemmy_db_schema::{
|
|||
person_mention::{PersonMention, PersonMentionInsertForm},
|
||||
post::Post,
|
||||
},
|
||||
traits::{Crud, DeleteableOrRemoveable},
|
||||
traits::Crud,
|
||||
SubscribedType,
|
||||
};
|
||||
use lemmy_db_views::structs::{CommentView, LocalUserView, PostView, PrivateMessageView};
|
||||
|
@ -32,7 +32,7 @@ pub async fn send_post_ws_message<OP: ToString + Send + OperationType + 'static>
|
|||
person_id: Option<PersonId>,
|
||||
context: &LemmyContext,
|
||||
) -> Result<PostResponse, LemmyError> {
|
||||
let post_view = PostView::read(context.pool(), post_id, person_id).await?;
|
||||
let post_view = PostView::read(context.pool(), post_id, person_id, Some(true)).await?;
|
||||
|
||||
let res = PostResponse { post_view };
|
||||
|
||||
|
@ -65,11 +65,7 @@ pub async fn send_comment_ws_message<OP: ToString + Send + OperationType + 'stat
|
|||
recipient_ids: Vec<LocalUserId>,
|
||||
context: &LemmyContext,
|
||||
) -> Result<CommentResponse, LemmyError> {
|
||||
let mut view = CommentView::read(context.pool(), comment_id, person_id).await?;
|
||||
|
||||
if view.comment.deleted || view.comment.removed {
|
||||
view.comment = view.comment.blank_out_deleted_or_removed_info();
|
||||
}
|
||||
let view = CommentView::read(context.pool(), comment_id, person_id).await?;
|
||||
|
||||
let mut res = CommentResponse {
|
||||
comment_view: view,
|
||||
|
@ -98,7 +94,8 @@ pub async fn send_community_ws_message<OP: ToString + Send + OperationType + 'st
|
|||
person_id: Option<PersonId>,
|
||||
context: &LemmyContext,
|
||||
) -> Result<CommunityResponse, LemmyError> {
|
||||
let community_view = CommunityView::read(context.pool(), community_id, person_id).await?;
|
||||
let community_view =
|
||||
CommunityView::read(context.pool(), community_id, person_id, Some(true)).await?;
|
||||
let discussion_languages = CommunityLanguage::read(context.pool(), community_id).await?;
|
||||
|
||||
let mut res = CommunityResponse {
|
||||
|
@ -124,12 +121,7 @@ pub async fn send_pm_ws_message<OP: ToString + Send + OperationType + 'static>(
|
|||
websocket_id: Option<ConnectionId>,
|
||||
context: &LemmyContext,
|
||||
) -> Result<PrivateMessageResponse, LemmyError> {
|
||||
let mut view = PrivateMessageView::read(context.pool(), private_message_id).await?;
|
||||
|
||||
// Blank out deleted or removed info
|
||||
if view.private_message.deleted {
|
||||
view.private_message = view.private_message.blank_out_deleted_or_removed_info();
|
||||
}
|
||||
let view = PrivateMessageView::read(context.pool(), private_message_id).await?;
|
||||
|
||||
let res = PrivateMessageResponse {
|
||||
private_message_view: view,
|
||||
|
|
|
@ -147,7 +147,7 @@ impl PerformCrud for CreateCommunity {
|
|||
|
||||
let person_id = local_user_view.person.id;
|
||||
let community_view =
|
||||
CommunityView::read(context.pool(), inserted_community.id, Some(person_id)).await?;
|
||||
CommunityView::read(context.pool(), inserted_community.id, Some(person_id), None).await?;
|
||||
let discussion_languages =
|
||||
CommunityLanguage::read(context.pool(), inserted_community.id).await?;
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@ use actix_web::web::Data;
|
|||
use lemmy_api_common::{
|
||||
community::{ListCommunities, ListCommunitiesResponse},
|
||||
context::LemmyContext,
|
||||
utils::{check_private_instance, get_local_user_view_from_jwt_opt},
|
||||
utils::{check_private_instance, get_local_user_view_from_jwt_opt, is_admin},
|
||||
};
|
||||
use lemmy_db_schema::{source::local_site::LocalSite, traits::DeleteableOrRemoveable};
|
||||
use lemmy_db_schema::source::local_site::LocalSite;
|
||||
use lemmy_db_views_actor::community_view::CommunityQuery;
|
||||
use lemmy_utils::{error::LemmyError, ConnectionId};
|
||||
|
||||
|
@ -24,37 +24,27 @@ impl PerformCrud for ListCommunities {
|
|||
get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
|
||||
.await?;
|
||||
let local_site = LocalSite::read(context.pool()).await?;
|
||||
let is_admin = local_user_view.as_ref().map(|luv| is_admin(luv).is_ok());
|
||||
|
||||
check_private_instance(&local_user_view, &local_site)?;
|
||||
|
||||
let person_id = local_user_view.clone().map(|l| l.person.id);
|
||||
|
||||
let sort = data.sort;
|
||||
let listing_type = data.type_;
|
||||
let page = data.page;
|
||||
let limit = data.limit;
|
||||
let local_user = local_user_view.map(|l| l.local_user);
|
||||
let mut communities = CommunityQuery::builder()
|
||||
let communities = CommunityQuery::builder()
|
||||
.pool(context.pool())
|
||||
.listing_type(listing_type)
|
||||
.sort(sort)
|
||||
.local_user(local_user.as_ref())
|
||||
.page(page)
|
||||
.limit(limit)
|
||||
.is_mod_or_admin(is_admin)
|
||||
.build()
|
||||
.list()
|
||||
.await?;
|
||||
|
||||
// Blank out deleted or removed info for non-logged in users
|
||||
if person_id.is_none() {
|
||||
for cv in communities
|
||||
.iter_mut()
|
||||
.filter(|cv| cv.community.deleted || cv.community.removed)
|
||||
{
|
||||
cv.community = cv.clone().community.blank_out_deleted_or_removed_info();
|
||||
}
|
||||
}
|
||||
|
||||
// Return the jwt
|
||||
Ok(ListCommunitiesResponse { communities })
|
||||
}
|
||||
|
|
|
@ -3,12 +3,17 @@ use actix_web::web::Data;
|
|||
use lemmy_api_common::{
|
||||
context::LemmyContext,
|
||||
post::{GetPost, GetPostResponse},
|
||||
utils::{check_private_instance, get_local_user_view_from_jwt_opt, mark_post_as_read},
|
||||
utils::{
|
||||
check_private_instance,
|
||||
get_local_user_view_from_jwt_opt,
|
||||
is_mod_or_admin_opt,
|
||||
mark_post_as_read,
|
||||
},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
aggregates::structs::{PersonPostAggregates, PersonPostAggregatesForm},
|
||||
source::{comment::Comment, local_site::LocalSite},
|
||||
traits::{Crud, DeleteableOrRemoveable},
|
||||
source::{comment::Comment, local_site::LocalSite, post::Post},
|
||||
traits::Crud,
|
||||
};
|
||||
use lemmy_db_views::structs::PostView;
|
||||
use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView};
|
||||
|
@ -32,7 +37,7 @@ impl PerformCrud for GetPost {
|
|||
|
||||
check_private_instance(&local_user_view, &local_site)?;
|
||||
|
||||
let person_id = local_user_view.map(|u| u.person.id);
|
||||
let person_id = local_user_view.as_ref().map(|u| u.person.id);
|
||||
|
||||
// I'd prefer fetching the post_view by a comment join, but it adds a lot of boilerplate
|
||||
let post_id = if let Some(id) = data.id {
|
||||
|
@ -46,7 +51,14 @@ impl PerformCrud for GetPost {
|
|||
Err(LemmyError::from_message("couldnt_find_post"))?
|
||||
};
|
||||
|
||||
let mut post_view = PostView::read(context.pool(), post_id, person_id)
|
||||
// Check to see if the person is a mod or admin, to show deleted / removed
|
||||
let community_id = Post::read(context.pool(), post_id).await?.community_id;
|
||||
let is_mod_or_admin =
|
||||
is_mod_or_admin_opt(context.pool(), local_user_view.as_ref(), Some(community_id))
|
||||
.await
|
||||
.is_ok();
|
||||
|
||||
let post_view = PostView::read(context.pool(), post_id, person_id, Some(is_mod_or_admin))
|
||||
.await
|
||||
.map_err(|e| LemmyError::from_error_message(e, "couldnt_find_post"))?;
|
||||
|
||||
|
@ -57,8 +69,12 @@ impl PerformCrud for GetPost {
|
|||
}
|
||||
|
||||
// Necessary for the sidebar subscribed
|
||||
let community_id = post_view.community.id;
|
||||
let mut community_view = CommunityView::read(context.pool(), community_id, person_id)
|
||||
let community_view = CommunityView::read(
|
||||
context.pool(),
|
||||
community_id,
|
||||
person_id,
|
||||
Some(is_mod_or_admin),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
|
||||
|
||||
|
@ -77,17 +93,6 @@ impl PerformCrud for GetPost {
|
|||
.map_err(|e| LemmyError::from_error_message(e, "couldnt_find_post"))?;
|
||||
}
|
||||
|
||||
// Blank out deleted or removed info for non-logged in users
|
||||
if person_id.is_none() {
|
||||
if post_view.post.deleted || post_view.post.removed {
|
||||
post_view.post = post_view.post.blank_out_deleted_or_removed_info();
|
||||
}
|
||||
|
||||
if community_view.community.deleted || community_view.community.removed {
|
||||
community_view.community = community_view.community.blank_out_deleted_or_removed_info();
|
||||
}
|
||||
}
|
||||
|
||||
let moderators = CommunityModeratorView::for_community(context.pool(), community_id).await?;
|
||||
|
||||
let online = context.chat_server().get_post_users_online(post_id)?;
|
||||
|
|
|
@ -5,7 +5,6 @@ use lemmy_api_common::{
|
|||
private_message::{GetPrivateMessages, PrivateMessagesResponse},
|
||||
utils::get_local_user_view_from_jwt,
|
||||
};
|
||||
use lemmy_db_schema::traits::DeleteableOrRemoveable;
|
||||
use lemmy_db_views::private_message_view::PrivateMessageQuery;
|
||||
use lemmy_utils::{error::LemmyError, ConnectionId};
|
||||
|
||||
|
@ -45,17 +44,6 @@ impl PerformCrud for GetPrivateMessages {
|
|||
}
|
||||
});
|
||||
|
||||
// Blank out deleted or removed info
|
||||
for pmv in messages
|
||||
.iter_mut()
|
||||
.filter(|pmv| pmv.private_message.deleted)
|
||||
{
|
||||
pmv.private_message = pmv
|
||||
.clone()
|
||||
.private_message
|
||||
.blank_out_deleted_or_removed_info();
|
||||
}
|
||||
|
||||
Ok(PrivateMessagesResponse {
|
||||
private_messages: messages,
|
||||
})
|
||||
|
|
|
@ -99,7 +99,8 @@ impl ActivityHandler for AcceptFollow {
|
|||
|
||||
// Send the Subscribed message over websocket
|
||||
// Re-read the community_view to get the new SubscribedType
|
||||
let community_view = CommunityView::read(context.pool(), community_id, Some(person_id)).await?;
|
||||
let community_view =
|
||||
CommunityView::read(context.pool(), community_id, Some(person_id), None).await?;
|
||||
|
||||
// Get the local_user_id
|
||||
let local_recipient_id = LocalUserView::read_person(context.pool(), person_id)
|
||||
|
|
|
@ -15,7 +15,7 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{comment::Comment, community::Community, local_site::LocalSite},
|
||||
traits::{Crud, DeleteableOrRemoveable},
|
||||
traits::Crud,
|
||||
};
|
||||
use lemmy_db_views::comment_view::CommentQuery;
|
||||
use lemmy_utils::{error::LemmyError, ConnectionId};
|
||||
|
@ -65,7 +65,7 @@ impl PerformApub for GetComments {
|
|||
let parent_path_cloned = parent_path.clone();
|
||||
let post_id = data.post_id;
|
||||
let local_user = local_user_view.map(|l| l.local_user);
|
||||
let mut comments = CommentQuery::builder()
|
||||
let comments = CommentQuery::builder()
|
||||
.pool(context.pool())
|
||||
.listing_type(Some(listing_type))
|
||||
.sort(sort)
|
||||
|
@ -83,14 +83,6 @@ impl PerformApub for GetComments {
|
|||
.await
|
||||
.map_err(|e| LemmyError::from_error_message(e, "couldnt_get_comments"))?;
|
||||
|
||||
// Blank out deleted or removed info
|
||||
for cv in comments
|
||||
.iter_mut()
|
||||
.filter(|cv| cv.comment.deleted || cv.comment.removed)
|
||||
{
|
||||
cv.comment = cv.clone().comment.blank_out_deleted_or_removed_info();
|
||||
}
|
||||
|
||||
Ok(GetCommentsResponse { comments })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,11 @@ use lemmy_api_common::{
|
|||
utils::{
|
||||
check_private_instance,
|
||||
get_local_user_view_from_jwt_opt,
|
||||
is_mod_or_admin_opt,
|
||||
listing_type_with_site_default,
|
||||
},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{community::Community, local_site::LocalSite},
|
||||
traits::DeleteableOrRemoveable,
|
||||
};
|
||||
use lemmy_db_schema::source::{community::Community, local_site::LocalSite};
|
||||
use lemmy_db_views::post_view::PostQuery;
|
||||
use lemmy_utils::{error::LemmyError, ConnectionId};
|
||||
|
||||
|
@ -38,8 +36,6 @@ impl PerformApub for GetPosts {
|
|||
|
||||
check_private_instance(&local_user_view, &local_site)?;
|
||||
|
||||
let is_logged_in = local_user_view.is_some();
|
||||
|
||||
let sort = data.sort;
|
||||
let listing_type = listing_type_with_site_default(data.type_, &local_site)?;
|
||||
|
||||
|
@ -56,7 +52,12 @@ impl PerformApub for GetPosts {
|
|||
};
|
||||
let saved_only = data.saved_only;
|
||||
|
||||
let mut posts = PostQuery::builder()
|
||||
let is_mod_or_admin =
|
||||
is_mod_or_admin_opt(context.pool(), local_user_view.as_ref(), community_id)
|
||||
.await
|
||||
.is_ok();
|
||||
|
||||
let posts = PostQuery::builder()
|
||||
.pool(context.pool())
|
||||
.local_user(local_user_view.map(|l| l.local_user).as_ref())
|
||||
.listing_type(Some(listing_type))
|
||||
|
@ -66,28 +67,12 @@ impl PerformApub for GetPosts {
|
|||
.saved_only(saved_only)
|
||||
.page(page)
|
||||
.limit(limit)
|
||||
.is_mod_or_admin(Some(is_mod_or_admin))
|
||||
.build()
|
||||
.list()
|
||||
.await
|
||||
.map_err(|e| LemmyError::from_error_message(e, "couldnt_get_posts"))?;
|
||||
|
||||
// Blank out deleted or removed info for non-logged in users
|
||||
if !is_logged_in {
|
||||
for pv in posts
|
||||
.iter_mut()
|
||||
.filter(|p| p.post.deleted || p.post.removed)
|
||||
{
|
||||
pv.post = pv.clone().post.blank_out_deleted_or_removed_info();
|
||||
}
|
||||
|
||||
for pv in posts
|
||||
.iter_mut()
|
||||
.filter(|p| p.community.deleted || p.community.removed)
|
||||
{
|
||||
pv.community = pv.clone().community.blank_out_deleted_or_removed_info();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(GetPostsResponse { posts })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use actix_web::web::Data;
|
|||
use lemmy_api_common::{
|
||||
community::{GetCommunity, GetCommunityResponse},
|
||||
context::LemmyContext,
|
||||
utils::{check_private_instance, get_local_user_view_from_jwt_opt},
|
||||
utils::{check_private_instance, get_local_user_view_from_jwt_opt, is_mod_or_admin_opt},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
impls::actor_language::default_post_language,
|
||||
|
@ -17,7 +17,6 @@ use lemmy_db_schema::{
|
|||
local_site::LocalSite,
|
||||
site::Site,
|
||||
},
|
||||
traits::DeleteableOrRemoveable,
|
||||
};
|
||||
use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView};
|
||||
use lemmy_utils::{error::LemmyError, ConnectionId};
|
||||
|
@ -57,16 +56,20 @@ impl PerformApub for GetCommunity {
|
|||
}
|
||||
};
|
||||
|
||||
let mut community_view = CommunityView::read(context.pool(), community_id, person_id)
|
||||
let is_mod_or_admin =
|
||||
is_mod_or_admin_opt(context.pool(), local_user_view.as_ref(), Some(community_id))
|
||||
.await
|
||||
.is_ok();
|
||||
|
||||
let community_view = CommunityView::read(
|
||||
context.pool(),
|
||||
community_id,
|
||||
person_id,
|
||||
Some(is_mod_or_admin),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
|
||||
|
||||
// Blank out deleted or removed info for non-logged in users
|
||||
if person_id.is_none() && (community_view.community.deleted || community_view.community.removed)
|
||||
{
|
||||
community_view.community = community_view.community.blank_out_deleted_or_removed_info();
|
||||
}
|
||||
|
||||
let moderators = CommunityModeratorView::for_community(context.pool(), community_id)
|
||||
.await
|
||||
.map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
|
||||
|
|
|
@ -3,7 +3,7 @@ use actix_web::web::Data;
|
|||
use lemmy_api_common::{
|
||||
context::LemmyContext,
|
||||
person::{GetPersonDetails, GetPersonDetailsResponse},
|
||||
utils::{check_private_instance, get_local_user_view_from_jwt_opt},
|
||||
utils::{check_private_instance, get_local_user_view_from_jwt_opt, is_admin},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{local_site::LocalSite, person::Person},
|
||||
|
@ -34,6 +34,7 @@ impl PerformApub for GetPersonDetails {
|
|||
get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
|
||||
.await?;
|
||||
let local_site = LocalSite::read(context.pool()).await?;
|
||||
let is_admin = local_user_view.as_ref().map(|luv| is_admin(luv).is_ok());
|
||||
|
||||
check_private_instance(&local_user_view, &local_site)?;
|
||||
|
||||
|
@ -71,6 +72,7 @@ impl PerformApub for GetPersonDetails {
|
|||
.saved_only(saved_only)
|
||||
.local_user(local_user.as_ref())
|
||||
.community_id(community_id)
|
||||
.is_mod_or_admin(is_admin)
|
||||
.page(page)
|
||||
.limit(limit);
|
||||
|
||||
|
|
|
@ -56,11 +56,11 @@ async fn convert_response(
|
|||
}
|
||||
Community(c) => {
|
||||
removed_or_deleted = c.deleted || c.removed;
|
||||
res.community = Some(CommunityView::read(pool, c.id, user_id).await?)
|
||||
res.community = Some(CommunityView::read(pool, c.id, user_id, None).await?)
|
||||
}
|
||||
Post(p) => {
|
||||
removed_or_deleted = p.deleted || p.removed;
|
||||
res.post = Some(PostView::read(pool, p.id, user_id).await?)
|
||||
res.post = Some(PostView::read(pool, p.id, user_id, None).await?)
|
||||
}
|
||||
Comment(c) => {
|
||||
removed_or_deleted = c.deleted || c.removed;
|
||||
|
|
|
@ -7,11 +7,10 @@ use actix_web::web::Data;
|
|||
use lemmy_api_common::{
|
||||
context::LemmyContext,
|
||||
site::{Search, SearchResponse},
|
||||
utils::{check_private_instance, get_local_user_view_from_jwt_opt},
|
||||
utils::{check_private_instance, get_local_user_view_from_jwt_opt, is_admin},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{community::Community, local_site::LocalSite},
|
||||
traits::DeleteableOrRemoveable,
|
||||
utils::post_to_comment_sort_type,
|
||||
SearchType,
|
||||
};
|
||||
|
@ -38,7 +37,8 @@ impl PerformApub for Search {
|
|||
|
||||
check_private_instance(&local_user_view, &local_site)?;
|
||||
|
||||
let person_id = local_user_view.as_ref().map(|u| u.person.id);
|
||||
let is_admin = local_user_view.as_ref().map(|luv| is_admin(luv).is_ok());
|
||||
|
||||
let local_user = local_user_view.map(|l| l.local_user);
|
||||
|
||||
let mut posts = Vec::new();
|
||||
|
@ -75,6 +75,7 @@ impl PerformApub for Search {
|
|||
.creator_id(creator_id)
|
||||
.local_user(local_user.as_ref())
|
||||
.search_term(Some(q))
|
||||
.is_mod_or_admin(is_admin)
|
||||
.page(page)
|
||||
.limit(limit)
|
||||
.build()
|
||||
|
@ -104,6 +105,7 @@ impl PerformApub for Search {
|
|||
.listing_type(listing_type)
|
||||
.search_term(Some(q))
|
||||
.local_user(local_user.as_ref())
|
||||
.is_mod_or_admin(is_admin)
|
||||
.page(page)
|
||||
.limit(limit)
|
||||
.build()
|
||||
|
@ -137,6 +139,7 @@ impl PerformApub for Search {
|
|||
.creator_id(creator_id)
|
||||
.local_user(local_user_.as_ref())
|
||||
.search_term(Some(q))
|
||||
.is_mod_or_admin(is_admin)
|
||||
.page(page)
|
||||
.limit(limit)
|
||||
.build()
|
||||
|
@ -173,6 +176,7 @@ impl PerformApub for Search {
|
|||
.listing_type(listing_type)
|
||||
.search_term(Some(q))
|
||||
.local_user(local_user.as_ref())
|
||||
.is_mod_or_admin(is_admin)
|
||||
.page(page)
|
||||
.limit(limit)
|
||||
.build()
|
||||
|
@ -205,6 +209,7 @@ impl PerformApub for Search {
|
|||
.community_actor_id(community_actor_id)
|
||||
.creator_id(creator_id)
|
||||
.url_search(Some(q))
|
||||
.is_mod_or_admin(is_admin)
|
||||
.page(page)
|
||||
.limit(limit)
|
||||
.build()
|
||||
|
@ -213,30 +218,6 @@ impl PerformApub for Search {
|
|||
}
|
||||
};
|
||||
|
||||
// Blank out deleted or removed info for non logged in users
|
||||
if person_id.is_none() {
|
||||
for cv in communities
|
||||
.iter_mut()
|
||||
.filter(|cv| cv.community.deleted || cv.community.removed)
|
||||
{
|
||||
cv.community = cv.clone().community.blank_out_deleted_or_removed_info();
|
||||
}
|
||||
|
||||
for pv in posts
|
||||
.iter_mut()
|
||||
.filter(|p| p.post.deleted || p.post.removed)
|
||||
{
|
||||
pv.post = pv.clone().post.blank_out_deleted_or_removed_info();
|
||||
}
|
||||
|
||||
for cv in comments
|
||||
.iter_mut()
|
||||
.filter(|cv| cv.comment.deleted || cv.comment.removed)
|
||||
{
|
||||
cv.comment = cv.clone().comment.blank_out_deleted_or_removed_info();
|
||||
}
|
||||
}
|
||||
|
||||
// Return the jwt
|
||||
Ok(SearchResponse {
|
||||
type_: search_type.to_string(),
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
CommentSavedForm,
|
||||
CommentUpdateForm,
|
||||
},
|
||||
traits::{Crud, DeleteableOrRemoveable, Likeable, Saveable},
|
||||
traits::{Crud, Likeable, Saveable},
|
||||
utils::{get_conn, naive_now, DbPool},
|
||||
};
|
||||
use diesel::{
|
||||
|
@ -240,13 +240,6 @@ impl Saveable for CommentSaved {
|
|||
}
|
||||
}
|
||||
|
||||
impl DeleteableOrRemoveable for Comment {
|
||||
fn blank_out_deleted_or_removed_info(mut self) -> Self {
|
||||
self.content = String::new();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{
|
||||
|
|
|
@ -12,11 +12,10 @@ use crate::{
|
|||
CommunityModeratorForm,
|
||||
CommunityPersonBan,
|
||||
CommunityPersonBanForm,
|
||||
CommunitySafe,
|
||||
CommunityUpdateForm,
|
||||
},
|
||||
},
|
||||
traits::{ApubActor, Bannable, Crud, DeleteableOrRemoveable, Followable, Joinable},
|
||||
traits::{ApubActor, Bannable, Crud, Followable, Joinable},
|
||||
utils::{functions::lower, get_conn, DbPool},
|
||||
SubscribedType,
|
||||
};
|
||||
|
@ -174,26 +173,6 @@ impl Joinable for CommunityModerator {
|
|||
}
|
||||
}
|
||||
|
||||
impl DeleteableOrRemoveable for CommunitySafe {
|
||||
fn blank_out_deleted_or_removed_info(mut self) -> Self {
|
||||
self.title = String::new();
|
||||
self.description = None;
|
||||
self.icon = None;
|
||||
self.banner = None;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl DeleteableOrRemoveable for Community {
|
||||
fn blank_out_deleted_or_removed_info(mut self) -> Self {
|
||||
self.title = String::new();
|
||||
self.description = None;
|
||||
self.icon = None;
|
||||
self.banner = None;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub enum CollectionType {
|
||||
Moderators,
|
||||
Featured,
|
||||
|
|
|
@ -26,7 +26,7 @@ use crate::{
|
|||
PostSavedForm,
|
||||
PostUpdateForm,
|
||||
},
|
||||
traits::{Crud, DeleteableOrRemoveable, Likeable, Readable, Saveable},
|
||||
traits::{Crud, Likeable, Readable, Saveable},
|
||||
utils::{get_conn, naive_now, DbPool, FETCH_LIMIT_MAX},
|
||||
};
|
||||
use ::url::Url;
|
||||
|
@ -317,20 +317,6 @@ impl Readable for PostRead {
|
|||
}
|
||||
}
|
||||
|
||||
impl DeleteableOrRemoveable for Post {
|
||||
fn blank_out_deleted_or_removed_info(mut self) -> Self {
|
||||
self.name = String::new();
|
||||
self.url = None;
|
||||
self.body = None;
|
||||
self.embed_title = None;
|
||||
self.embed_description = None;
|
||||
self.embed_video_url = None;
|
||||
self.thumbnail_url = None;
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
newtypes::{DbUrl, PersonId, PrivateMessageId},
|
||||
schema::private_message::dsl::{ap_id, private_message, read, recipient_id},
|
||||
source::private_message::{PrivateMessage, PrivateMessageInsertForm, PrivateMessageUpdateForm},
|
||||
traits::{Crud, DeleteableOrRemoveable},
|
||||
traits::Crud,
|
||||
utils::{get_conn, DbPool},
|
||||
};
|
||||
use diesel::{dsl::insert_into, result::Error, ExpressionMethods, QueryDsl};
|
||||
|
@ -86,13 +86,6 @@ impl PrivateMessage {
|
|||
}
|
||||
}
|
||||
|
||||
impl DeleteableOrRemoveable for PrivateMessage {
|
||||
fn blank_out_deleted_or_removed_info(mut self) -> Self {
|
||||
self.content = String::new();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{
|
||||
|
|
|
@ -140,11 +140,6 @@ pub trait Reportable {
|
|||
Self: Sized;
|
||||
}
|
||||
|
||||
// TODO these should be removed, there should be another way to do this
|
||||
pub trait DeleteableOrRemoveable {
|
||||
fn blank_out_deleted_or_removed_info(self) -> Self;
|
||||
}
|
||||
|
||||
pub trait ToSafe {
|
||||
type SafeColumns;
|
||||
fn safe_columns_tuple() -> Self::SafeColumns;
|
||||
|
|
|
@ -68,24 +68,14 @@ impl PostView {
|
|||
pool: &DbPool,
|
||||
post_id: PostId,
|
||||
my_person_id: Option<PersonId>,
|
||||
is_mod_or_admin: Option<bool>,
|
||||
) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
||||
// The left join below will return None in this case
|
||||
let person_id_join = my_person_id.unwrap_or(PersonId(-1));
|
||||
let (
|
||||
post,
|
||||
creator,
|
||||
community,
|
||||
creator_banned_from_community,
|
||||
counts,
|
||||
follower,
|
||||
saved,
|
||||
read,
|
||||
creator_blocked,
|
||||
post_like,
|
||||
unread_comments,
|
||||
) = post::table
|
||||
let person_alias_1 = diesel::alias!(person as person1);
|
||||
let mut query = post::table
|
||||
.find(post_id)
|
||||
.inner_join(person::table)
|
||||
.inner_join(community::table)
|
||||
|
@ -144,6 +134,14 @@ impl PostView {
|
|||
.and(person_post_aggregates::person_id.eq(person_id_join)),
|
||||
),
|
||||
)
|
||||
// Used to check if you are the post creator
|
||||
.left_join(
|
||||
person_alias_1.on(
|
||||
post::creator_id
|
||||
.eq(person_alias_1.field(person::id))
|
||||
.and(person_alias_1.field(person::id).eq(person_id_join)),
|
||||
),
|
||||
)
|
||||
.select((
|
||||
post::all_columns,
|
||||
Person::safe_columns_tuple(),
|
||||
|
@ -160,8 +158,38 @@ impl PostView {
|
|||
post_aggregates::comments,
|
||||
),
|
||||
))
|
||||
.first::<PostViewTuple>(conn)
|
||||
.await?;
|
||||
.into_boxed();
|
||||
|
||||
// If you are not a moderator, exclude deleted or removed content
|
||||
if !is_mod_or_admin.unwrap_or(true) {
|
||||
// If you are not the creator, then remove the other fields.
|
||||
query = query
|
||||
.filter(
|
||||
person_alias_1.field(person::id).is_null().and(
|
||||
post::removed
|
||||
.eq(false)
|
||||
.and(post::deleted.eq(false))
|
||||
.and(community::removed.eq(false))
|
||||
.and(community::deleted.eq(false)),
|
||||
),
|
||||
)
|
||||
// If you are the creator, keep them
|
||||
.or_filter(person_alias_1.field(person::id).is_not_null())
|
||||
}
|
||||
|
||||
let (
|
||||
post,
|
||||
creator,
|
||||
community,
|
||||
creator_banned_from_community,
|
||||
counts,
|
||||
follower,
|
||||
saved,
|
||||
read,
|
||||
creator_blocked,
|
||||
post_like,
|
||||
unread_comments,
|
||||
) = query.first::<PostViewTuple>(conn).await?;
|
||||
|
||||
// If a person is given, then my_vote, if None, should be 0, not null
|
||||
// Necessary to differentiate between other person's votes
|
||||
|
@ -201,6 +229,8 @@ pub struct PostQuery<'a> {
|
|||
search_term: Option<String>,
|
||||
url_search: Option<String>,
|
||||
saved_only: Option<bool>,
|
||||
/// Used to show deleted or removed posts for admins
|
||||
is_mod_or_admin: Option<bool>,
|
||||
page: Option<i64>,
|
||||
limit: Option<i64>,
|
||||
}
|
||||
|
@ -212,6 +242,7 @@ impl<'a> PostQuery<'a> {
|
|||
// The left join below will return None in this case
|
||||
let person_id_join = self.local_user.map(|l| l.person_id).unwrap_or(PersonId(-1));
|
||||
let local_user_id_join = self.local_user.map(|l| l.id).unwrap_or(LocalUserId(-1));
|
||||
let person_alias_1 = diesel::alias!(person as person1);
|
||||
|
||||
let mut query = post::table
|
||||
.inner_join(person::table)
|
||||
|
@ -285,6 +316,14 @@ impl<'a> PostQuery<'a> {
|
|||
.and(local_user_language::local_user_id.eq(local_user_id_join)),
|
||||
),
|
||||
)
|
||||
// Used to check if you are the post creator
|
||||
.left_join(
|
||||
person_alias_1.on(
|
||||
post::creator_id
|
||||
.eq(person_alias_1.field(person::id))
|
||||
.and(person_alias_1.field(person::id).eq(person_id_join)),
|
||||
),
|
||||
)
|
||||
.select((
|
||||
post::all_columns,
|
||||
Person::safe_columns_tuple(),
|
||||
|
@ -303,6 +342,23 @@ impl<'a> PostQuery<'a> {
|
|||
))
|
||||
.into_boxed();
|
||||
|
||||
// If you are not a moderator, exclude deleted or removed content
|
||||
if !self.is_mod_or_admin.unwrap_or(true) {
|
||||
// If you are not the creator, then remove the other fields.
|
||||
query = query
|
||||
.filter(
|
||||
person_alias_1.field(person::id).is_null().and(
|
||||
post::removed
|
||||
.eq(false)
|
||||
.and(post::deleted.eq(false))
|
||||
.and(community::removed.eq(false))
|
||||
.and(community::deleted.eq(false)),
|
||||
),
|
||||
)
|
||||
// If you are the creator, keep them
|
||||
.or_filter(person_alias_1.field(person::id).is_not_null())
|
||||
}
|
||||
|
||||
if let Some(listing_type) = self.listing_type {
|
||||
match listing_type {
|
||||
ListingType::Subscribed => {
|
||||
|
@ -349,7 +405,6 @@ impl<'a> PostQuery<'a> {
|
|||
);
|
||||
}
|
||||
|
||||
// If its for a specific person, show the removed / deleted
|
||||
if let Some(creator_id) = self.creator_id {
|
||||
query = query.filter(post::creator_id.eq(creator_id));
|
||||
}
|
||||
|
@ -424,13 +479,7 @@ impl<'a> PostQuery<'a> {
|
|||
|
||||
let (limit, offset) = limit_and_offset(self.page, self.limit)?;
|
||||
|
||||
query = query
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
.filter(post::removed.eq(false))
|
||||
.filter(post::deleted.eq(false))
|
||||
.filter(community::removed.eq(false))
|
||||
.filter(community::deleted.eq(false));
|
||||
query = query.limit(limit).offset(offset);
|
||||
|
||||
debug!("Post View Query: {:?}", debug_query::<Pg, _>(&query));
|
||||
|
||||
|
@ -615,8 +664,12 @@ mod tests {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let post_listing_single_with_person =
|
||||
PostView::read(pool, data.inserted_post.id, Some(data.inserted_person.id))
|
||||
let post_listing_single_with_person = PostView::read(
|
||||
pool,
|
||||
data.inserted_post.id,
|
||||
Some(data.inserted_person.id),
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -670,7 +723,8 @@ mod tests {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let read_post_listing_single_no_person = PostView::read(pool, data.inserted_post.id, None)
|
||||
let read_post_listing_single_no_person =
|
||||
PostView::read(pool, data.inserted_post.id, None, None)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -37,12 +37,13 @@ impl CommunityView {
|
|||
pool: &DbPool,
|
||||
community_id: CommunityId,
|
||||
my_person_id: Option<PersonId>,
|
||||
is_mod_or_admin: Option<bool>,
|
||||
) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
// The left join below will return None in this case
|
||||
let person_id_join = my_person_id.unwrap_or(PersonId(-1));
|
||||
|
||||
let (community, counts, follower, blocked) = community::table
|
||||
let mut query = community::table
|
||||
.find(community_id)
|
||||
.inner_join(community_aggregates::table)
|
||||
.left_join(
|
||||
|
@ -65,8 +66,16 @@ impl CommunityView {
|
|||
community_follower::all_columns.nullable(),
|
||||
community_block::all_columns.nullable(),
|
||||
))
|
||||
.first::<CommunityViewTuple>(conn)
|
||||
.await?;
|
||||
.into_boxed();
|
||||
|
||||
// Hide deleted and removed for non-admins or mods
|
||||
if !is_mod_or_admin.unwrap_or(true) {
|
||||
query = query
|
||||
.filter(community::removed.eq(false))
|
||||
.filter(community::deleted.eq(false));
|
||||
}
|
||||
|
||||
let (community, counts, follower, blocked) = query.first::<CommunityViewTuple>(conn).await?;
|
||||
|
||||
Ok(CommunityView {
|
||||
community,
|
||||
|
@ -116,6 +125,7 @@ pub struct CommunityQuery<'a> {
|
|||
sort: Option<SortType>,
|
||||
local_user: Option<&'a LocalUser>,
|
||||
search_term: Option<String>,
|
||||
is_mod_or_admin: Option<bool>,
|
||||
page: Option<i64>,
|
||||
limit: Option<i64>,
|
||||
}
|
||||
|
@ -159,6 +169,13 @@ impl<'a> CommunityQuery<'a> {
|
|||
.or_filter(community::title.ilike(searcher));
|
||||
};
|
||||
|
||||
// Hide deleted and removed for non-admins or mods
|
||||
if !self.is_mod_or_admin.unwrap_or(true) {
|
||||
query = query
|
||||
.filter(community::removed.eq(false))
|
||||
.filter(community::deleted.eq(false));
|
||||
}
|
||||
|
||||
match self.sort.unwrap_or(SortType::Hot) {
|
||||
SortType::New => query = query.order_by(community::published.desc()),
|
||||
SortType::TopAll => query = query.order_by(community_aggregates::subscribers.desc()),
|
||||
|
|
Loading…
Reference in a new issue