Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User / community blocking. Fixes #426 #1604

Merged
merged 15 commits into from
Aug 19, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
A first pass at user / community blocking. #426
  • Loading branch information
dessalines committed Aug 19, 2021
commit 9e8a4807ece1f260b4a9856847713c580df8a1eb
8 changes: 8 additions & 0 deletions crates/api/src/comment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use lemmy_api_common::{
blocking,
check_community_ban,
check_downvotes_enabled,
check_person_block,
comment::*,
get_local_user_view_from_jwt,
};
Expand Down Expand Up @@ -151,6 +152,13 @@ impl Perform for CreateCommentLike {
)
.await?;

check_person_block(
local_user_view.person.id,
orig_comment.get_recipient_id(),
context.pool(),
)
.await?;

// Add parent user to recipients
let recipient_id = orig_comment.get_recipient_id();
if let Ok(local_recipient) = blocking(context.pool(), move |conn| {
Expand Down
44 changes: 44 additions & 0 deletions crates/api/src/community.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ use lemmy_apub::{
use lemmy_db_queries::{
source::{comment::Comment_, community::CommunityModerator_, post::Post_},
Bannable,
Blockable,
Crud,
Followable,
Joinable,
};
use lemmy_db_schema::source::{
comment::Comment,
community::*,
community_block::{CommunityBlock, CommunityBlockForm},
moderator::*,
person::Person,
post::Post,
Expand Down Expand Up @@ -107,6 +109,48 @@ impl Perform for FollowCommunity {
}
}

#[async_trait::async_trait(?Send)]
impl Perform for BlockCommunity {
type Response = CommunityResponse;

async fn perform(
&self,
context: &Data<LemmyContext>,
_websocket_id: Option<ConnectionId>,
) -> Result<CommunityResponse, LemmyError> {
let data: &BlockCommunity = &self;
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;

let community_id = data.community_id;
let person_id = local_user_view.person.id;
let community_block_form = CommunityBlockForm {
person_id,
community_id,
};

if data.block {
let block = move |conn: &'_ _| CommunityBlock::block(conn, &community_block_form);
if blocking(context.pool(), block).await?.is_err() {
return Err(ApiError::err("community_block_already_exists").into());
}
} else {
let unblock = move |conn: &'_ _| CommunityBlock::unblock(conn, &community_block_form);
if blocking(context.pool(), unblock).await?.is_err() {
return Err(ApiError::err("community_block_already_exists").into());
}
}

// TODO does any federated stuff need to be done here?
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we want to federate any of this, I'm guessing no.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could send an unsubscribe to the community. That way, if the local user was the only follower of a remote community, it wont try to deliver its posts to the instance (where they would be ignored).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hrm... for now lets let unsubscribe be its own activity.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean sending an Undo/Follow to the community, i'm not proposing any changes to the apub code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I just added unfollowing that community and sending the abup undofollowcommunity


let community_view = blocking(context.pool(), move |conn| {
CommunityView::read(conn, community_id, Some(person_id))
})
.await??;

Ok(CommunityResponse { community_view })
}
}

#[async_trait::async_trait(?Send)]
impl Perform for BanFromCommunity {
type Response = BanFromCommunityResponse;
Expand Down
12 changes: 12 additions & 0 deletions crates/api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,15 @@ pub async fn match_websocket_operation(
UserOperation::GetReplies => do_websocket_operation::<GetReplies>(context, id, op, data).await,
UserOperation::AddAdmin => do_websocket_operation::<AddAdmin>(context, id, op, data).await,
UserOperation::BanPerson => do_websocket_operation::<BanPerson>(context, id, op, data).await,
UserOperation::BlockPerson => {
do_websocket_operation::<BlockPerson>(context, id, op, data).await
}
dessalines marked this conversation as resolved.
Show resolved Hide resolved
UserOperation::GetPersonMentions => {
do_websocket_operation::<GetPersonMentions>(context, id, op, data).await
}
UserOperation::GetBlockedPersons => {
do_websocket_operation::<GetBlockedPersons>(context, id, op, data).await
}
UserOperation::MarkPersonMentionAsRead => {
do_websocket_operation::<MarkPersonMentionAsRead>(context, id, op, data).await
}
Expand Down Expand Up @@ -95,9 +101,15 @@ pub async fn match_websocket_operation(
UserOperation::FollowCommunity => {
do_websocket_operation::<FollowCommunity>(context, id, op, data).await
}
UserOperation::BlockCommunity => {
do_websocket_operation::<BlockCommunity>(context, id, op, data).await
}
UserOperation::GetFollowedCommunities => {
do_websocket_operation::<GetFollowedCommunities>(context, id, op, data).await
}
UserOperation::GetBlockedCommunities => {
do_websocket_operation::<GetBlockedCommunities>(context, id, op, data).await
}
UserOperation::BanFromCommunity => {
do_websocket_operation::<BanFromCommunity>(context, id, op, data).await
}
Expand Down
106 changes: 105 additions & 1 deletion crates/api/src/local_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ use chrono::Duration;
use lemmy_api_common::{
blocking,
collect_moderated_communities,
community::{GetFollowedCommunities, GetFollowedCommunitiesResponse},
community::{
GetBlockedCommunities,
GetBlockedCommunitiesResponse,
GetFollowedCommunities,
GetFollowedCommunitiesResponse,
},
get_local_user_view_from_jwt,
is_admin,
password_length_check,
Expand All @@ -27,6 +32,7 @@ use lemmy_db_queries::{
post::Post_,
private_message::PrivateMessage_,
},
Blockable,
Crud,
SortType,
};
Expand All @@ -39,6 +45,7 @@ use lemmy_db_schema::{
moderator::*,
password_reset_request::*,
person::*,
person_block::{PersonBlock, PersonBlockForm},
person_mention::*,
post::Post,
private_message::PrivateMessage,
Expand All @@ -52,8 +59,10 @@ use lemmy_db_views::{
post_report_view::PostReportView,
};
use lemmy_db_views_actor::{
community_block_view::CommunityBlockView,
community_follower_view::CommunityFollowerView,
community_moderator_view::CommunityModeratorView,
person_block_view::PersonBlockView,
person_mention_view::{PersonMentionQueryBuilder, PersonMentionView},
person_view::PersonViewSafe,
};
Expand Down Expand Up @@ -471,6 +480,53 @@ impl Perform for BanPerson {
}
}

#[async_trait::async_trait(?Send)]
impl Perform for BlockPerson {
type Response = BlockPersonResponse;

async fn perform(
&self,
context: &Data<LemmyContext>,
_websocket_id: Option<ConnectionId>,
) -> Result<BlockPersonResponse, LemmyError> {
let data: &BlockPerson = &self;
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;

let recipient_id = data.person_id;
let person_id = local_user_view.person.id;
let community_block_form = PersonBlockForm {
person_id,
recipient_id,
};

if data.block {
let block = move |conn: &'_ _| PersonBlock::block(conn, &community_block_form);
if blocking(context.pool(), block).await?.is_err() {
return Err(ApiError::err("person_block_already_exists").into());
}
} else {
let unblock = move |conn: &'_ _| PersonBlock::unblock(conn, &community_block_form);
if blocking(context.pool(), unblock).await?.is_err() {
return Err(ApiError::err("person_block_already_exists").into());
}
}

// TODO does any federated stuff need to be done here?

let person_view = blocking(context.pool(), move |conn| {
PersonViewSafe::read(conn, recipient_id)
})
.await??;

let res = BlockPersonResponse {
person_view,
blocked: data.block,
};

Ok(res)
}
}

#[async_trait::async_trait(?Send)]
impl Perform for GetReplies {
type Response = GetRepliesResponse;
Expand Down Expand Up @@ -802,3 +858,51 @@ impl Perform for GetFollowedCommunities {
Ok(GetFollowedCommunitiesResponse { communities })
}
}

#[async_trait::async_trait(?Send)]
impl Perform for GetBlockedCommunities {
type Response = GetBlockedCommunitiesResponse;

async fn perform(
&self,
context: &Data<LemmyContext>,
_websocket_id: Option<ConnectionId>,
) -> Result<GetBlockedCommunitiesResponse, LemmyError> {
let data: &GetBlockedCommunities = &self;
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;

let person_id = local_user_view.person.id;
let communities = blocking(context.pool(), move |conn| {
CommunityBlockView::for_person(conn, person_id)
})
.await?
.map_err(|_| ApiError::err("system_err_login"))?;

// Return the jwt
Ok(GetBlockedCommunitiesResponse { communities })
}
}

#[async_trait::async_trait(?Send)]
impl Perform for GetBlockedPersons {
type Response = GetBlockedPersonsResponse;

async fn perform(
&self,
context: &Data<LemmyContext>,
_websocket_id: Option<ConnectionId>,
) -> Result<GetBlockedPersonsResponse, LemmyError> {
let data: &GetBlockedPersons = &self;
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;

let person_id = local_user_view.person.id;
let persons = blocking(context.pool(), move |conn| {
PersonBlockView::for_person(conn, person_id)
})
.await?
.map_err(|_| ApiError::err("system_err_login"))?;

// Return the jwt
Ok(GetBlockedPersonsResponse { persons })
}
}
3 changes: 3 additions & 0 deletions crates/api/src/post.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use lemmy_api_common::{
blocking,
check_community_ban,
check_downvotes_enabled,
check_person_block,
get_local_user_view_from_jwt,
is_mod_or_admin,
mark_post_as_read,
Expand Down Expand Up @@ -48,6 +49,8 @@ impl Perform for CreatePostLike {

check_community_ban(local_user_view.person.id, post.community_id, context.pool()).await?;

check_person_block(local_user_view.person.id, post.creator_id, context.pool()).await?;
dessalines marked this conversation as resolved.
Show resolved Hide resolved

let like_form = PostLikeForm {
post_id: data.post_id,
person_id: local_user_view.person.id,
Expand Down
18 changes: 18 additions & 0 deletions crates/api_common/src/community.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use lemmy_db_schema::{CommunityId, PersonId};
use lemmy_db_views_actor::{
community_block_view::CommunityBlockView,
community_follower_view::CommunityFollowerView,
community_moderator_view::CommunityModeratorView,
community_view::CommunityView,
Expand Down Expand Up @@ -116,6 +117,13 @@ pub struct FollowCommunity {
pub auth: String,
}

#[derive(Deserialize)]
pub struct BlockCommunity {
pub community_id: CommunityId,
pub block: bool,
pub auth: String,
}

#[derive(Deserialize)]
pub struct GetFollowedCommunities {
pub auth: String,
Expand All @@ -126,6 +134,16 @@ pub struct GetFollowedCommunitiesResponse {
pub communities: Vec<CommunityFollowerView>,
}

#[derive(Deserialize)]
pub struct GetBlockedCommunities {
pub auth: String,
}

#[derive(Serialize)]
pub struct GetBlockedCommunitiesResponse {
pub communities: Vec<CommunityBlockView>,
}

#[derive(Deserialize)]
pub struct TransferCommunity {
pub community_id: CommunityId,
Expand Down
16 changes: 16 additions & 0 deletions crates/api_common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use diesel::PgConnection;
use lemmy_db_queries::{
source::{
community::{CommunityModerator_, Community_},
person_block::PersonBlock_,
site::Site_,
},
Crud,
Expand All @@ -21,6 +22,7 @@ use lemmy_db_schema::{
comment::Comment,
community::{Community, CommunityModerator},
person::Person,
person_block::PersonBlock,
person_mention::{PersonMention, PersonMentionForm},
post::{Post, PostRead, PostReadForm},
site::Site,
Expand Down Expand Up @@ -353,6 +355,20 @@ pub async fn check_community_ban(
}
}

pub async fn check_person_block(
person_id: PersonId,
recipient_id: PersonId,
pool: &DbPool,
) -> Result<(), LemmyError> {
// TODO the person and recipient might be reversed
let is_blocked = move |conn: &'_ _| PersonBlock::read(conn, person_id, recipient_id).is_ok();
if blocking(pool, is_blocked).await? {
Err(ApiError::err("person_block").into())
} else {
Ok(())
}
}

pub async fn check_downvotes_enabled(score: i16, pool: &DbPool) -> Result<(), LemmyError> {
if score == -1 {
let site = blocking(pool, move |conn| Site::read_simple(conn)).await??;
Expand Down
Loading