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

Rewrite remaining activities #1712

Merged
merged 11 commits into from
Aug 19, 2021
Prev Previous commit
Next Next commit
Simplify delete activity implementation
  • Loading branch information
Nutomic committed Aug 13, 2021
commit e65897a3503f1a9e7b3a20155964385e2da39ba1
139 changes: 40 additions & 99 deletions crates/apub/src/activities/deletion/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,18 @@ use crate::{
activities::{
comment::send_websocket_message as send_comment_message,
community::send_websocket_message as send_community_message,
deletion::{verify_delete_activity, DeletableObjects},
post::send_websocket_message as send_post_message,
verify_activity,
verify_mod_action,
verify_person_in_community,
},
fetcher::{
community::get_or_fetch_and_upsert_community,
objects::get_or_fetch_and_insert_post_or_comment,
person::get_or_fetch_and_upsert_person,
},
ActorType,
fetcher::person::get_or_fetch_and_upsert_person,
CommunityType,
PostOrComment,
};
use activitystreams::activity::kind::DeleteType;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{values::PublicUrl, verify_urls_match, ActivityCommonFields, ActivityHandler};
use lemmy_db_queries::{
source::{comment::Comment_, community::Community_, post::Post_},
Crud,
};
use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
use lemmy_apub_lib::{values::PublicUrl, ActivityCommonFields, ActivityHandler};
use lemmy_db_queries::source::{comment::Comment_, community::Community_, post::Post_};
use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post};
use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
Expand Down Expand Up @@ -56,20 +46,14 @@ impl ActivityHandler for DeletePostCommentOrCommunity {
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_activity(self.common())?;
let object_community =
get_or_fetch_and_upsert_community(&self.object, context, request_counter).await;
// deleting a community (set counter 0 to only fetch from local db)
if object_community.is_ok() {
verify_mod_action(&self.common.actor, self.object.clone(), context).await?;
}
// deleting a post or comment
else {
verify_person_in_community(&self.common().actor, &self.cc[0], context, request_counter)
.await?;
let object_creator =
get_post_or_comment_actor_id(&self.object, context, request_counter).await?;
verify_urls_match(&self.common.actor, &object_creator)?;
}
verify_delete_activity(
&self.object,
&self.cc[0],
&self.common,
context,
request_counter,
)
.await?;
Ok(())
}

Expand All @@ -78,54 +62,34 @@ impl ActivityHandler for DeletePostCommentOrCommunity {
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let object_community =
get_or_fetch_and_upsert_community(&self.object, context, request_counter).await;
// deleting a community
if let Ok(community) = object_community {
if community.local {
// repeat these checks just to be sure
verify_person_in_community(&self.common().actor, &self.cc[0], context, request_counter)
.await?;
verify_mod_action(&self.common.actor, self.object.clone(), context).await?;
let mod_ =
get_or_fetch_and_upsert_person(&self.common.actor, context, request_counter).await?;
community.send_delete(mod_, context).await?;
}
let deleted_community = blocking(context.pool(), move |conn| {
Community::update_deleted(conn, community.id, true)
})
.await??;

send_community_message(
deleted_community.id,
UserOperationCrud::DeleteCommunity,
context,
)
.await
}
// deleting a post or comment
else {
match get_or_fetch_and_insert_post_or_comment(&self.object, context, request_counter).await? {
PostOrComment::Post(post) => {
let deleted_post = blocking(context.pool(), move |conn| {
Post::update_deleted(conn, post.id, true)
})
.await??;
send_post_message(deleted_post.id, UserOperationCrud::EditPost, context).await
}
PostOrComment::Comment(comment) => {
let deleted_comment = blocking(context.pool(), move |conn| {
Comment::update_deleted(conn, comment.id, true)
})
.await??;
send_comment_message(
deleted_comment.id,
vec![],
UserOperationCrud::EditComment,
context,
)
.await
use UserOperationCrud::*;
match DeletableObjects::read_from_db(&self.object, context).await? {
DeletableObjects::Community(community) => {
if community.local {
let mod_ =
get_or_fetch_and_upsert_person(&self.common.actor, context, request_counter).await?;
community.send_delete(mod_, context).await?;
}

let deleted_community = blocking(context.pool(), move |conn| {
Community::update_deleted(conn, community.id, true)
})
.await??;
send_community_message(deleted_community.id, DeleteCommunity, context).await
}
DeletableObjects::Post(post) => {
let deleted_post = blocking(context.pool(), move |conn| {
Post::update_deleted(conn, post.id, true)
})
.await??;
send_post_message(deleted_post.id, EditPost, context).await
}
DeletableObjects::Comment(comment) => {
let deleted_comment = blocking(context.pool(), move |conn| {
Comment::update_deleted(conn, comment.id, true)
})
.await??;
send_comment_message(deleted_comment.id, vec![], EditComment, context).await
}
}
}
Expand All @@ -134,26 +98,3 @@ impl ActivityHandler for DeletePostCommentOrCommunity {
&self.common
}
}

async fn get_post_or_comment_actor_id(
object: &Url,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<Url, LemmyError> {
let actor_id =
match get_or_fetch_and_insert_post_or_comment(object, context, request_counter).await? {
PostOrComment::Post(post) => {
let creator_id = post.creator_id;
blocking(context.pool(), move |conn| Person::read(conn, creator_id))
.await??
.actor_id()
}
PostOrComment::Comment(comment) => {
let creator_id = comment.creator_id;
blocking(context.pool(), move |conn| Person::read(conn, creator_id))
.await??
.actor_id()
}
};
Ok(actor_id)
}
82 changes: 82 additions & 0 deletions crates/apub/src/activities/deletion/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,84 @@
use crate::{
activities::{verify_mod_action, verify_person_in_community},
ActorType,
};
use lemmy_api_common::blocking;
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields};
use lemmy_db_queries::ApubObject;
use lemmy_db_schema::{
source::{comment::Comment, community::Community, post::Post},
DbUrl,
};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;

pub mod delete;
pub mod undo_delete;

pub enum DeletableObjects {
Community(Box<Community>),
Comment(Box<Comment>),
Post(Box<Post>),
}

impl DeletableObjects {
pub(crate) async fn read_from_db(
ap_id: &Url,
context: &LemmyContext,
) -> Result<DeletableObjects, LemmyError> {
let id: DbUrl = ap_id.clone().into();

if let Some(c) = DeletableObjects::read_type_from_db::<Community>(id.clone(), context).await? {
return Ok(DeletableObjects::Community(Box::new(c)));
}
if let Some(p) = DeletableObjects::read_type_from_db::<Post>(id.clone(), context).await? {
return Ok(DeletableObjects::Post(Box::new(p)));
}
if let Some(c) = DeletableObjects::read_type_from_db::<Comment>(id.clone(), context).await? {
return Ok(DeletableObjects::Comment(Box::new(c)));
}
Err(diesel::NotFound.into())
}

// TODO: a method like this should be provided by fetcher module
async fn read_type_from_db<Type: ApubObject + Send + 'static>(
ap_id: DbUrl,
context: &LemmyContext,
) -> Result<Option<Type>, LemmyError> {
blocking(context.pool(), move |conn| {
Type::read_from_apub_id(conn, &ap_id).ok()
})
.await
}
}

pub(in crate::activities::deletion) async fn verify_delete_activity(
object: &Url,
cc: &Url,
common: &ActivityCommonFields,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let object = DeletableObjects::read_from_db(object, context).await?;
match object {
DeletableObjects::Community(c) => {
if c.local {
// can only do this check for local community, in remote case it would try to fetch the
// deleted community (which fails)
verify_person_in_community(&common.actor, cc, context, request_counter).await?;
}
verify_mod_action(&common.actor, c.actor_id(), context).await?;
}
DeletableObjects::Post(p) => {
verify_person_in_community(&common.actor, cc, context, request_counter).await?;
// domain of post ap_id and post.creator ap_id are identical, so we just check the former
verify_domains_match(&common.actor, &p.ap_id.into())?;
}
DeletableObjects::Comment(c) => {
verify_person_in_community(&common.actor, cc, context, request_counter).await?;
verify_domains_match(&common.actor, &c.ap_id.into())?;
}
}
Ok(())
}
110 changes: 39 additions & 71 deletions crates/apub/src/activities/deletion/undo_delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,16 @@ use crate::{
activities::{
comment::send_websocket_message as send_comment_message,
community::send_websocket_message as send_community_message,
deletion::delete::DeletePostCommentOrCommunity,
deletion::{delete::DeletePostCommentOrCommunity, verify_delete_activity, DeletableObjects},
post::send_websocket_message as send_post_message,
verify_activity,
verify_mod_action,
verify_person_in_community,
},
fetcher::{
community::get_or_fetch_and_upsert_community,
objects::get_or_fetch_and_insert_post_or_comment,
person::get_or_fetch_and_upsert_person,
},
fetcher::person::get_or_fetch_and_upsert_person,
CommunityType,
PostOrComment,
};
use activitystreams::activity::kind::UndoType;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{values::PublicUrl, verify_urls_match, ActivityCommonFields, ActivityHandler};
use lemmy_apub_lib::{values::PublicUrl, ActivityCommonFields, ActivityHandler};
use lemmy_db_queries::source::{comment::Comment_, community::Community_, post::Post_};
use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post};
use lemmy_utils::LemmyError;
Expand Down Expand Up @@ -46,18 +39,14 @@ impl ActivityHandler for UndoDeletePostCommentOrCommunity {
) -> Result<(), LemmyError> {
verify_activity(self.common())?;
self.object.verify(context, request_counter).await?;
let object_community =
get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await;
// restoring a community
if object_community.is_ok() {
verify_mod_action(&self.common.actor, self.object.object.clone(), context).await?;
}
// restoring a post or comment
else {
verify_person_in_community(&self.common().actor, &self.cc[0], context, request_counter)
.await?;
verify_urls_match(&self.common.actor, &self.object.common().actor)?;
}
verify_delete_activity(
&self.object.object,
&self.cc[0],
&self.common,
context,
request_counter,
)
.await?;
Ok(())
}

Expand All @@ -66,56 +55,35 @@ impl ActivityHandler for UndoDeletePostCommentOrCommunity {
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let object_community =
get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await;
// restoring a community
if let Ok(community) = object_community {
if community.local {
// repeat these checks just to be sure
verify_person_in_community(&self.common().actor, &self.cc[0], context, request_counter)
.await?;
verify_mod_action(&self.common.actor, self.object.object.clone(), context).await?;
let mod_ =
get_or_fetch_and_upsert_person(&self.common.actor, context, request_counter).await?;
community.send_undo_delete(mod_, context).await?;
}
let deleted_community = blocking(context.pool(), move |conn| {
Community::update_deleted(conn, community.id, false)
})
.await??;

send_community_message(
deleted_community.id,
UserOperationCrud::EditCommunity,
context,
)
.await
}
// restoring a post or comment
else {
match get_or_fetch_and_insert_post_or_comment(&self.object.object, context, request_counter)
.await?
{
PostOrComment::Post(post) => {
let deleted_post = blocking(context.pool(), move |conn| {
Post::update_deleted(conn, post.id, false)
})
.await??;
send_post_message(deleted_post.id, UserOperationCrud::EditPost, context).await
}
PostOrComment::Comment(comment) => {
let deleted_comment = blocking(context.pool(), move |conn| {
Comment::update_deleted(conn, comment.id, false)
})
.await??;
send_comment_message(
deleted_comment.id,
vec![],
UserOperationCrud::EditComment,
context,
)
.await
use UserOperationCrud::*;
let object = DeletableObjects::read_from_db(&self.object.object, context).await?;
match object {
DeletableObjects::Community(community) => {
if community.local {
let mod_ =
get_or_fetch_and_upsert_person(&self.common.actor, context, request_counter).await?;
community.send_undo_delete(mod_, context).await?;
}

let deleted_community = blocking(context.pool(), move |conn| {
Community::update_deleted(conn, community.id, false)
})
.await??;
send_community_message(deleted_community.id, EditCommunity, context).await
}
DeletableObjects::Post(post) => {
let deleted_post = blocking(context.pool(), move |conn| {
Post::update_deleted(conn, post.id, false)
})
.await??;
send_post_message(deleted_post.id, EditPost, context).await
}
DeletableObjects::Comment(comment) => {
let deleted_comment = blocking(context.pool(), move |conn| {
Comment::update_deleted(conn, comment.id, false)
})
.await??;
send_comment_message(deleted_comment.id, vec![], EditComment, context).await
}
}
}
Expand Down