Merge pull request 'Dont include full objects with remove/delete activities' (#113) from delete-with-id into main

Reviewed-on: https://yerbamate.dev/LemmyNet/lemmy/pulls/113
pull/1201/head
dessalines 2020-10-13 18:31:11 +00:00
commit d55e38d4a6
11 changed files with 273 additions and 618 deletions

View File

@ -1,27 +1,19 @@
use crate::{
activities::receive::{
announce_if_community_is_local,
get_actor_as_user,
receive_unhandled_activity,
},
fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
ActorType,
FromApub,
GroupExt,
PageExt,
use crate::activities::receive::{
announce_if_community_is_local,
find_by_id,
get_actor_as_user,
FindResults,
};
use activitystreams::{activity::Delete, base::AnyBase, object::Note, prelude::*};
use activitystreams::{activity::Delete, base::AnyBase, prelude::*};
use actix_web::HttpResponse;
use anyhow::Context;
use lemmy_db::{
comment::{Comment, CommentForm},
comment::Comment,
comment_view::CommentView,
community::{Community, CommunityForm},
community::Community,
community_view::CommunityView,
naive_now,
post::{Post, PostForm},
post::Post,
post_view::PostView,
Crud,
};
use lemmy_structs::{
blocking,
@ -41,108 +33,66 @@ pub async fn receive_delete(
context: &LemmyContext,
) -> Result<HttpResponse, LemmyError> {
let delete = Delete::from_any_base(activity)?.context(location_info!())?;
match delete.object().as_single_kind_str() {
Some("Page") => receive_delete_post(delete, context).await,
Some("Note") => receive_delete_comment(delete, context).await,
Some("Group") => receive_delete_community(delete, context).await,
_ => receive_unhandled_activity(delete),
let object = delete
.object()
.to_owned()
.single_xsd_any_uri()
.context(location_info!())?;
// Ensure that delete activity comes from the same domain as the object
delete.id(object.domain().context(location_info!())?)?;
match find_by_id(context, object).await {
Ok(FindResults::Post(p)) => receive_delete_post(context, delete, p).await,
Ok(FindResults::Comment(c)) => receive_delete_comment(context, delete, c).await,
Ok(FindResults::Community(c)) => receive_delete_community(context, delete, c).await,
// if we dont have the object, no need to do anything
Err(_) => Ok(HttpResponse::Ok().finish()),
}
}
async fn receive_delete_post(
delete: Delete,
context: &LemmyContext,
delete: Delete,
post: Post,
) -> Result<HttpResponse, LemmyError> {
let user = get_actor_as_user(&delete, context).await?;
let page = PageExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post_ap_id = PostForm::from_apub(&page, context, Some(user.actor_id()?))
.await?
.get_ap_id()?;
let post = get_or_fetch_and_insert_post(&post_ap_id, context).await?;
let post_form = PostForm {
name: post.name.to_owned(),
url: post.url.to_owned(),
body: post.body.to_owned(),
creator_id: post.creator_id.to_owned(),
community_id: post.community_id,
removed: None,
deleted: Some(true),
nsfw: post.nsfw,
locked: None,
stickied: None,
updated: Some(naive_now()),
embed_title: post.embed_title,
embed_description: post.embed_description,
embed_html: post.embed_html,
thumbnail_url: post.thumbnail_url,
ap_id: Some(post.ap_id),
local: post.local,
published: None,
};
let post_id = post.id;
blocking(context.pool(), move |conn| {
Post::update(conn, post_id, &post_form)
let deleted_post = blocking(context.pool(), move |conn| {
Post::update_deleted(conn, post.id, true)
})
.await??;
// Refetch the view
let post_id = post.id;
let post_id = deleted_post.id;
let post_view = blocking(context.pool(), move |conn| {
PostView::read(conn, post_id, None)
})
.await??;
let res = PostResponse { post: post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::EditPost,
post: res,
websocket_id: None,
});
let user = get_actor_as_user(&delete, context).await?;
announce_if_community_is_local(delete, &user, context).await?;
Ok(HttpResponse::Ok().finish())
}
async fn receive_delete_comment(
delete: Delete,
context: &LemmyContext,
delete: Delete,
comment: Comment,
) -> Result<HttpResponse, LemmyError> {
let user = get_actor_as_user(&delete, context).await?;
let note = Note::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let comment_ap_id = CommentForm::from_apub(&note, context, Some(user.actor_id()?))
.await?
.get_ap_id()?;
let comment = get_or_fetch_and_insert_comment(&comment_ap_id, context).await?;
let comment_form = CommentForm {
content: comment.content.to_owned(),
parent_id: comment.parent_id,
post_id: comment.post_id,
creator_id: comment.creator_id,
removed: None,
deleted: Some(true),
read: None,
published: None,
updated: Some(naive_now()),
ap_id: Some(comment.ap_id),
local: comment.local,
};
let comment_id = comment.id;
blocking(context.pool(), move |conn| {
Comment::update(conn, comment_id, &comment_form)
let deleted_comment = blocking(context.pool(), move |conn| {
Comment::update_deleted(conn, comment.id, true)
})
.await??;
// Refetch the view
let comment_id = comment.id;
let comment_id = deleted_comment.id;
let comment_view = blocking(context.pool(), move |conn| {
CommentView::read(conn, comment_id, None)
})
@ -155,62 +105,28 @@ async fn receive_delete_comment(
recipient_ids,
form_id: None,
};
context.chat_server().do_send(SendComment {
op: UserOperation::EditComment,
comment: res,
websocket_id: None,
});
let user = get_actor_as_user(&delete, context).await?;
announce_if_community_is_local(delete, &user, context).await?;
Ok(HttpResponse::Ok().finish())
}
async fn receive_delete_community(
delete: Delete,
context: &LemmyContext,
delete: Delete,
community: Community,
) -> Result<HttpResponse, LemmyError> {
let group = GroupExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let user = get_actor_as_user(&delete, context).await?;
let community_actor_id = CommunityForm::from_apub(&group, context, Some(user.actor_id()?))
.await?
.actor_id
.context(location_info!())?;
let community = blocking(context.pool(), move |conn| {
Community::read_from_actor_id(conn, &community_actor_id)
let deleted_community = blocking(context.pool(), move |conn| {
Community::update_deleted(conn, community.id, true)
})
.await??;
let community_form = CommunityForm {
name: community.name.to_owned(),
title: community.title.to_owned(),
description: community.description.to_owned(),
category_id: community.category_id, // Note: need to keep this due to foreign key constraint
creator_id: community.creator_id, // Note: need to keep this due to foreign key constraint
removed: None,
published: None,
updated: Some(naive_now()),
deleted: Some(true),
nsfw: community.nsfw,
actor_id: Some(community.actor_id),
local: community.local,
private_key: community.private_key,
public_key: community.public_key,
last_refreshed_at: None,
icon: Some(community.icon.to_owned()),
banner: Some(community.banner.to_owned()),
};
let community_id = community.id;
blocking(context.pool(), move |conn| {
Community::update(conn, community_id, &community_form)
})
.await??;
let community_id = community.id;
let community_id = deleted_community.id;
let res = CommunityResponse {
community: blocking(context.pool(), move |conn| {
CommunityView::read(conn, community_id, None)
@ -219,7 +135,6 @@ async fn receive_delete_community(
};
let community_id = res.community.id;
context.chat_server().do_send(SendCommunityRoomMessage {
op: UserOperation::EditCommunity,
response: res,
@ -227,6 +142,7 @@ async fn receive_delete_community(
websocket_id: None,
});
let user = get_actor_as_user(&delete, context).await?;
announce_if_community_is_local(delete, &user, context).await?;
Ok(HttpResponse::Ok().finish())
}

View File

@ -9,7 +9,9 @@ use activitystreams::{
};
use actix_web::HttpResponse;
use anyhow::Context;
use lemmy_db::user::User_;
use diesel::result::Error::NotFound;
use lemmy_db::{comment::Comment, community::Community, post::Post, user::User_};
use lemmy_structs::blocking;
use lemmy_utils::{location_info, LemmyError};
use lemmy_websocket::LemmyContext;
use log::debug;
@ -68,7 +70,7 @@ where
Ok(())
}
pub(in crate) async fn get_actor_as_user<T, A>(
pub(crate) async fn get_actor_as_user<T, A>(
activity: &T,
context: &LemmyContext,
) -> Result<User_, LemmyError>
@ -79,3 +81,43 @@ where
let user_uri = actor.as_single_xsd_any_uri().context(location_info!())?;
get_or_fetch_and_upsert_user(&user_uri, context).await
}
pub(crate) enum FindResults {
Comment(Comment),
Community(Community),
Post(Post),
}
pub(crate) async fn find_by_id(
context: &LemmyContext,
apub_id: Url,
) -> Result<FindResults, LemmyError> {
let ap_id = apub_id.to_string();
let community = blocking(context.pool(), move |conn| {
Community::read_from_actor_id(conn, &ap_id)
})
.await?;
if let Ok(c) = community {
return Ok(FindResults::Community(c));
}
let ap_id = apub_id.to_string();
let post = blocking(context.pool(), move |conn| {
Post::read_from_apub_id(conn, &ap_id)
})
.await?;
if let Ok(p) = post {
return Ok(FindResults::Post(p));
}
let ap_id = apub_id.to_string();
let comment = blocking(context.pool(), move |conn| {
Comment::read_from_apub_id(conn, &ap_id)
})
.await?;
if let Ok(c) = comment {
return Ok(FindResults::Comment(c));
}
return Err(NotFound.into());
}

View File

@ -1,27 +1,17 @@
use crate::{
activities::receive::{
announce_if_community_is_local,
get_actor_as_user,
receive_unhandled_activity,
},
fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
activities::receive::{find_by_id, get_actor_as_user, FindResults},
ActorType,
FromApub,
GroupExt,
PageExt,
};
use activitystreams::{activity::Remove, base::AnyBase, object::Note, prelude::*};
use activitystreams::{activity::Remove, base::AnyBase, error::DomainError, prelude::*};
use actix_web::HttpResponse;
use anyhow::{anyhow, Context};
use anyhow::Context;
use lemmy_db::{
comment::{Comment, CommentForm},
comment::Comment,
comment_view::CommentView,
community::{Community, CommunityForm},
community::Community,
community_view::CommunityView,
naive_now,
post::{Post, PostForm},
post::Post,
post_view::PostView,
Crud,
};
use lemmy_structs::{
blocking,
@ -52,112 +42,69 @@ pub async fn receive_remove(
.map(|c| c.as_xsd_any_uri())
.flatten()
.context(location_info!())?;
let object = remove
.object()
.to_owned()
.single_xsd_any_uri()
.context(location_info!())?;
// Ensure that remove comes from the same domain as the community
if actor.actor_id()?.domain() != community_id.domain() {
return Err(anyhow!("Remove receive are only allowed on local objects").into());
return Err(DomainError.into());
}
match remove.object().as_single_kind_str() {
Some("Page") => receive_remove_post(remove, context).await,
Some("Note") => receive_remove_comment(remove, context).await,
Some("Group") => receive_remove_community(remove, context).await,
_ => receive_unhandled_activity(remove),
// Ensure that remove activity comes from the same domain as the community
remove.id(community_id.domain().context(location_info!())?)?;
match find_by_id(context, object).await {
Ok(FindResults::Post(p)) => receive_remove_post(context, remove, p).await,
Ok(FindResults::Comment(c)) => receive_remove_comment(context, remove, c).await,
Ok(FindResults::Community(c)) => receive_remove_community(context, remove, c).await,
// if we dont have the object, no need to do anything
Err(_) => Ok(HttpResponse::Ok().finish()),
}
}
async fn receive_remove_post(
remove: Remove,
context: &LemmyContext,
_remove: Remove,
post: Post,
) -> Result<HttpResponse, LemmyError> {
let mod_ = get_actor_as_user(&remove, context).await?;
let page = PageExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post_ap_id = PostForm::from_apub(&page, context, None)
.await?
.get_ap_id()?;
let post = get_or_fetch_and_insert_post(&post_ap_id, context).await?;
let post_form = PostForm {
name: post.name.to_owned(),
url: post.url.to_owned(),
body: post.body.to_owned(),
creator_id: post.creator_id.to_owned(),
community_id: post.community_id,
removed: Some(true),
deleted: None,
nsfw: post.nsfw,
locked: None,
stickied: None,
updated: Some(naive_now()),
embed_title: post.embed_title,
embed_description: post.embed_description,
embed_html: post.embed_html,
thumbnail_url: post.thumbnail_url,
ap_id: Some(post.ap_id),
local: post.local,
published: None,
};
let post_id = post.id;
blocking(context.pool(), move |conn| {
Post::update(conn, post_id, &post_form)
let removed_post = blocking(context.pool(), move |conn| {
Post::update_removed(conn, post.id, true)
})
.await??;
// Refetch the view
let post_id = post.id;
let post_id = removed_post.id;
let post_view = blocking(context.pool(), move |conn| {
PostView::read(conn, post_id, None)
})
.await??;
let res = PostResponse { post: post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::EditPost,
post: res,
websocket_id: None,
});
announce_if_community_is_local(remove, &mod_, context).await?;
Ok(HttpResponse::Ok().finish())
}
async fn receive_remove_comment(
remove: Remove,
context: &LemmyContext,
_remove: Remove,
comment: Comment,
) -> Result<HttpResponse, LemmyError> {
let mod_ = get_actor_as_user(&remove, context).await?;
let note = Note::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let comment_ap_id = CommentForm::from_apub(&note, context, None)
.await?
.get_ap_id()?;
let comment = get_or_fetch_and_insert_comment(&comment_ap_id, context).await?;
let comment_form = CommentForm {
content: comment.content.to_owned(),
parent_id: comment.parent_id,
post_id: comment.post_id,
creator_id: comment.creator_id,
removed: Some(true),
deleted: None,
read: None,
published: None,
updated: Some(naive_now()),
ap_id: Some(comment.ap_id),
local: comment.local,
};
let comment_id = comment.id;
blocking(context.pool(), move |conn| {
Comment::update(conn, comment_id, &comment_form)
let removed_comment = blocking(context.pool(), move |conn| {
Comment::update_removed(conn, comment.id, true)
})
.await??;
// Refetch the view
let comment_id = comment.id;
let comment_id = removed_comment.id;
let comment_view = blocking(context.pool(), move |conn| {
CommentView::read(conn, comment_id, None)
})
@ -170,62 +117,26 @@ async fn receive_remove_comment(
recipient_ids,
form_id: None,
};
context.chat_server().do_send(SendComment {
op: UserOperation::EditComment,
comment: res,
websocket_id: None,
});
announce_if_community_is_local(remove, &mod_, context).await?;
Ok(HttpResponse::Ok().finish())
}
async fn receive_remove_community(
remove: Remove,
context: &LemmyContext,
_remove: Remove,
community: Community,
) -> Result<HttpResponse, LemmyError> {
let mod_ = get_actor_as_user(&remove, context).await?;
let group = GroupExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let community_actor_id = CommunityForm::from_apub(&group, context, Some(mod_.actor_id()?))
.await?
.actor_id
.context(location_info!())?;
let community = blocking(context.pool(), move |conn| {
Community::read_from_actor_id(conn, &community_actor_id)
let removed_community = blocking(context.pool(), move |conn| {
Community::update_removed(conn, community.id, true)
})
.await??;
let community_form = CommunityForm {
name: community.name.to_owned(),
title: community.title.to_owned(),
description: community.description.to_owned(),
category_id: community.category_id, // Note: need to keep this due to foreign key constraint
creator_id: community.creator_id, // Note: need to keep this due to foreign key constraint
removed: Some(true),
published: None,
updated: Some(naive_now()),
deleted: None,
nsfw: community.nsfw,
actor_id: Some(community.actor_id),
local: community.local,
private_key: community.private_key,
public_key: community.public_key,
last_refreshed_at: None,
icon: Some(community.icon.to_owned()),
banner: Some(community.banner.to_owned()),
};
let community_id = community.id;
blocking(context.pool(), move |conn| {
Community::update(conn, community_id, &community_form)
})
.await??;
let community_id = community.id;
let community_id = removed_community.id;
let res = CommunityResponse {
community: blocking(context.pool(), move |conn| {
CommunityView::read(conn, community_id, None)
@ -234,7 +145,6 @@ async fn receive_remove_community(
};
let community_id = res.community.id;
context.chat_server().do_send(SendCommunityRoomMessage {
op: UserOperation::EditCommunity,
response: res,
@ -242,6 +152,5 @@ async fn receive_remove_community(
websocket_id: None,
});
announce_if_community_is_local(remove, &mod_, context).await?;
Ok(HttpResponse::Ok().finish())
}

View File

@ -1,14 +1,11 @@
use crate::{
activities::receive::{
announce_if_community_is_local,
get_actor_as_user,
receive_unhandled_activity,
undo_comment::*,
undo_post::*,
},
ActorType,
FromApub,
GroupExt,
use crate::activities::receive::{
announce_if_community_is_local,
find_by_id,
get_actor_as_user,
receive_unhandled_activity,
undo_comment::*,
undo_post::*,
FindResults,
};
use activitystreams::{
activity::*,
@ -17,12 +14,7 @@ use activitystreams::{
};
use actix_web::HttpResponse;
use anyhow::{anyhow, Context};
use lemmy_db::{
community::{Community, CommunityForm},
community_view::CommunityView,
naive_now,
Crud,
};
use lemmy_db::{community::Community, community_view::CommunityView};
use lemmy_structs::{blocking, community::CommunityResponse};
use lemmy_utils::{location_info, LemmyError};
use lemmy_websocket::{messages::SendCommunityRoomMessage, LemmyContext, UserOperation};
@ -69,15 +61,18 @@ async fn receive_undo_delete(
let delete = Delete::from_any_base(undo.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
check_is_undo_valid(&undo, &delete)?;
let type_ = delete
let object = delete
.object()
.as_single_kind_str()
.to_owned()
.single_xsd_any_uri()
.context(location_info!())?;
match type_ {
"Note" => receive_undo_delete_comment(undo, &delete, context).await,
"Page" => receive_undo_delete_post(undo, &delete, context).await,
"Group" => receive_undo_delete_community(undo, &delete, context).await,
d => Err(anyhow!("Undo Delete type {} not supported", d).into()),
match find_by_id(context, object).await {
Ok(FindResults::Post(p)) => receive_undo_delete_post(context, undo, p).await,
Ok(FindResults::Comment(c)) => receive_undo_delete_comment(context, undo, c).await,
Ok(FindResults::Community(c)) => receive_undo_delete_community(context, undo, c).await,
// if we dont have the object, no need to do anything
Err(_) => Ok(HttpResponse::Ok().finish()),
}
}
@ -89,15 +84,17 @@ async fn receive_undo_remove(
.context(location_info!())?;
check_is_undo_valid(&undo, &remove)?;
let type_ = remove
let object = remove
.object()
.as_single_kind_str()
.to_owned()
.single_xsd_any_uri()
.context(location_info!())?;
match type_ {
"Note" => receive_undo_remove_comment(undo, &remove, context).await,
"Page" => receive_undo_remove_post(undo, &remove, context).await,
"Group" => receive_undo_remove_community(undo, &remove, context).await,
d => Err(anyhow!("Undo Delete type {} not supported", d).into()),
match find_by_id(context, object).await {
Ok(FindResults::Post(p)) => receive_undo_remove_post(context, undo, p).await,
Ok(FindResults::Comment(c)) => receive_undo_remove_comment(context, undo, c).await,
Ok(FindResults::Community(c)) => receive_undo_remove_community(context, undo, c).await,
// if we dont have the object, no need to do anything
Err(_) => Ok(HttpResponse::Ok().finish()),
}
}
@ -137,51 +134,16 @@ async fn receive_undo_dislike(
}
async fn receive_undo_delete_community(
undo: Undo,
delete: &Delete,
context: &LemmyContext,
undo: Undo,
community: Community,
) -> Result<HttpResponse, LemmyError> {
let user = get_actor_as_user(delete, context).await?;
let group = GroupExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let community_actor_id = CommunityForm::from_apub(&group, context, Some(user.actor_id()?))
.await?
.actor_id
.context(location_info!())?;
let community = blocking(context.pool(), move |conn| {
Community::read_from_actor_id(conn, &community_actor_id)
let deleted_community = blocking(context.pool(), move |conn| {
Community::update_deleted(conn, community.id, false)
})
.await??;
let community_form = CommunityForm {
name: community.name.to_owned(),
title: community.title.to_owned(),
description: community.description.to_owned(),
category_id: community.category_id, // Note: need to keep this due to foreign key constraint
creator_id: community.creator_id, // Note: need to keep this due to foreign key constraint
removed: None,
published: None,
updated: Some(naive_now()),
deleted: Some(false),
nsfw: community.nsfw,
actor_id: Some(community.actor_id),
local: community.local,
private_key: community.private_key,
public_key: community.public_key,
last_refreshed_at: None,
icon: Some(community.icon.to_owned()),
banner: Some(community.banner.to_owned()),
};
let community_id = community.id;
blocking(context.pool(), move |conn| {
Community::update(conn, community_id, &community_form)
})
.await??;
let community_id = community.id;
let community_id = deleted_community.id;
let res = CommunityResponse {
community: blocking(context.pool(), move |conn| {
CommunityView::read(conn, community_id, None)
@ -190,7 +152,6 @@ async fn receive_undo_delete_community(
};
let community_id = res.community.id;
context.chat_server().do_send(SendCommunityRoomMessage {
op: UserOperation::EditCommunity,
response: res,
@ -198,56 +159,22 @@ async fn receive_undo_delete_community(
websocket_id: None,
});
let user = get_actor_as_user(&undo, context).await?;
announce_if_community_is_local(undo, &user, context).await?;
Ok(HttpResponse::Ok().finish())
}
async fn receive_undo_remove_community(
undo: Undo,
remove: &Remove,
context: &LemmyContext,
undo: Undo,
community: Community,
) -> Result<HttpResponse, LemmyError> {
let mod_ = get_actor_as_user(remove, context).await?;
let group = GroupExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let community_actor_id = CommunityForm::from_apub(&group, context, Some(mod_.actor_id()?))
.await?
.actor_id
.context(location_info!())?;
let community = blocking(context.pool(), move |conn| {
Community::read_from_actor_id(conn, &community_actor_id)
let removed_community = blocking(context.pool(), move |conn| {
Community::update_removed(conn, community.id, false)
})
.await??;
let community_form = CommunityForm {
name: community.name.to_owned(),
title: community.title.to_owned(),
description: community.description.to_owned(),
category_id: community.category_id, // Note: need to keep this due to foreign key constraint
creator_id: community.creator_id, // Note: need to keep this due to foreign key constraint
removed: Some(false),
published: None,
updated: Some(naive_now()),
deleted: None,
nsfw: community.nsfw,
actor_id: Some(community.actor_id),
local: community.local,
private_key: community.private_key,
public_key: community.public_key,
last_refreshed_at: None,
icon: Some(community.icon.to_owned()),
banner: Some(community.banner.to_owned()),
};
let community_id = community.id;
blocking(context.pool(), move |conn| {
Community::update(conn, community_id, &community_form)
})
.await??;
let community_id = community.id;
let community_id = removed_community.id;
let res = CommunityResponse {
community: blocking(context.pool(), move |conn| {
CommunityView::read(conn, community_id, None)
@ -264,6 +191,7 @@ async fn receive_undo_remove_community(
websocket_id: None,
});
let mod_ = get_actor_as_user(&undo, context).await?;
announce_if_community_is_local(undo, &mod_, context).await?;
Ok(HttpResponse::Ok().finish())
}

View File

@ -1,7 +1,6 @@
use crate::{
activities::receive::{announce_if_community_is_local, get_actor_as_user},
fetcher::get_or_fetch_and_insert_comment,
ActorType,
FromApub,
};
use activitystreams::{activity::*, object::Note, prelude::*};
@ -10,8 +9,6 @@ use anyhow::Context;
use lemmy_db::{
comment::{Comment, CommentForm, CommentLike},
comment_view::CommentView,
naive_now,
Crud,
Likeable,
};
use lemmy_structs::{blocking, comment::CommentResponse};
@ -115,41 +112,17 @@ pub(crate) async fn receive_undo_dislike_comment(
}
pub(crate) async fn receive_undo_delete_comment(
undo: Undo,
delete: &Delete,
context: &LemmyContext,
undo: Undo,
comment: Comment,
) -> Result<HttpResponse, LemmyError> {
let user = get_actor_as_user(delete, context).await?;
let note = Note::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let comment_ap_id = CommentForm::from_apub(&note, context, Some(user.actor_id()?))
.await?
.get_ap_id()?;
let comment = get_or_fetch_and_insert_comment(&comment_ap_id, context).await?;
let comment_form = CommentForm {
content: comment.content.to_owned(),
parent_id: comment.parent_id,
post_id: comment.post_id,
creator_id: comment.creator_id,
removed: None,
deleted: Some(false),
read: None,
published: None,
updated: Some(naive_now()),
ap_id: Some(comment.ap_id),
local: comment.local,
};
let comment_id = comment.id;
blocking(context.pool(), move |conn| {
Comment::update(conn, comment_id, &comment_form)
let deleted_comment = blocking(context.pool(), move |conn| {
Comment::update_deleted(conn, comment.id, false)
})
.await??;
// Refetch the view
let comment_id = comment.id;
let comment_id = deleted_comment.id;
let comment_view = blocking(context.pool(), move |conn| {
CommentView::read(conn, comment_id, None)
})
@ -169,46 +142,23 @@ pub(crate) async fn receive_undo_delete_comment(
websocket_id: None,
});
let user = get_actor_as_user(&undo, context).await?;
announce_if_community_is_local(undo, &user, context).await?;
Ok(HttpResponse::Ok().finish())
}
pub(crate) async fn receive_undo_remove_comment(
undo: Undo,
remove: &Remove,
context: &LemmyContext,
undo: Undo,
comment: Comment,
) -> Result<HttpResponse, LemmyError> {
let mod_ = get_actor_as_user(remove, context).await?;
let note = Note::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let comment_ap_id = CommentForm::from_apub(&note, context, None)
.await?
.get_ap_id()?;
let comment = get_or_fetch_and_insert_comment(&comment_ap_id, context).await?;
let comment_form = CommentForm {
content: comment.content.to_owned(),
parent_id: comment.parent_id,
post_id: comment.post_id,
creator_id: comment.creator_id,
removed: Some(false),
deleted: None,
read: None,
published: None,
updated: Some(naive_now()),
ap_id: Some(comment.ap_id),
local: comment.local,
};
let comment_id = comment.id;
blocking(context.pool(), move |conn| {
Comment::update(conn, comment_id, &comment_form)
let removed_comment = blocking(context.pool(), move |conn| {
Comment::update_removed(conn, comment.id, false)
})
.await??;
// Refetch the view
let comment_id = comment.id;
let comment_id = removed_comment.id;
let comment_view = blocking(context.pool(), move |conn| {
CommentView::read(conn, comment_id, None)
})
@ -228,6 +178,7 @@ pub(crate) async fn receive_undo_remove_comment(
websocket_id: None,
});
let mod_ = get_actor_as_user(&undo, context).await?;
announce_if_community_is_local(undo, &mod_, context).await?;
Ok(HttpResponse::Ok().finish())
}

View File

@ -1,7 +1,6 @@
use crate::{
activities::receive::{announce_if_community_is_local, get_actor_as_user},
fetcher::get_or_fetch_and_insert_post,
ActorType,
FromApub,
PageExt,
};
@ -9,10 +8,8 @@ use activitystreams::{activity::*, prelude::*};
use actix_web::HttpResponse;
use anyhow::Context;
use lemmy_db::{
naive_now,
post::{Post, PostForm, PostLike},
post_view::PostView,
Crud,
Likeable,
};
use lemmy_structs::{blocking, post::PostResponse};
@ -104,108 +101,46 @@ pub(crate) async fn receive_undo_dislike_post(
}
pub(crate) async fn receive_undo_delete_post(
undo: Undo,
delete: &Delete,
context: &LemmyContext,
undo: Undo,
post: Post,
) -> Result<HttpResponse, LemmyError> {
let user = get_actor_as_user(delete, context).await?;
let page = PageExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post_ap_id = PostForm::from_apub(&page, context, Some(user.actor_id()?))
.await?
.get_ap_id()?;
let post = get_or_fetch_and_insert_post(&post_ap_id, context).await?;
let post_form = PostForm {
name: post.name.to_owned(),
url: post.url.to_owned(),
body: post.body.to_owned(),
creator_id: post.creator_id.to_owned(),
community_id: post.community_id,
removed: None,
deleted: Some(false),
nsfw: post.nsfw,
locked: None,
stickied: None,
updated: Some(naive_now()),
embed_title: post.embed_title,
embed_description: post.embed_description,
embed_html: post.embed_html,
thumbnail_url: post.thumbnail_url,
ap_id: Some(post.ap_id),
local: post.local,
published: None,
};
let post_id = post.id;
blocking(context.pool(), move |conn| {
Post::update(conn, post_id, &post_form)
let deleted_post = blocking(context.pool(), move |conn| {
Post::update_deleted(conn, post.id, false)
})
.await??;
// Refetch the view
let post_id = post.id;
let post_id = deleted_post.id;
let post_view = blocking(context.pool(), move |conn| {
PostView::read(conn, post_id, None)
})
.await??;
let res = PostResponse { post: post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::EditPost,
post: res,
websocket_id: None,
});
let user = get_actor_as_user(&undo, context).await?;
announce_if_community_is_local(undo, &user, context).await?;
Ok(HttpResponse::Ok().finish())
}
pub(crate) async fn receive_undo_remove_post(
undo: Undo,
remove: &Remove,
context: &LemmyContext,
undo: Undo,
post: Post,
) -> Result<HttpResponse, LemmyError> {
let mod_ = get_actor_as_user(remove, context).await?;
let page = PageExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post_ap_id = PostForm::from_apub(&page, context, None)
.await?
.get_ap_id()?;
let post = get_or_fetch_and_insert_post(&post_ap_id, context).await?;
let post_form = PostForm {
name: post.name.to_owned(),
url: post.url.to_owned(),
body: post.body.to_owned(),
creator_id: post.creator_id.to_owned(),
community_id: post.community_id,
removed: Some(false),
deleted: None,
nsfw: post.nsfw,
locked: None,
stickied: None,
updated: Some(naive_now()),
embed_title: post.embed_title,
embed_description: post.embed_description,
embed_html: post.embed_html,
thumbnail_url: post.thumbnail_url,
ap_id: Some(post.ap_id),
local: post.local,
published: None,
};
let post_id = post.id;
blocking(context.pool(), move |conn| {
Post::update(conn, post_id, &post_form)
let removed_post = blocking(context.pool(), move |conn| {
Post::update_removed(conn, post.id, false)
})
.await??;
// Refetch the view
let post_id = post.id;
let post_id = removed_post.id;
let post_view = blocking(context.pool(), move |conn| {
PostView::read(conn, post_id, None)
})
@ -219,6 +154,7 @@ pub(crate) async fn receive_undo_remove_post(
websocket_id: None,
});
let mod_ = get_actor_as_user(&undo, context).await?;
announce_if_community_is_local(undo, &mod_, context).await?;
Ok(HttpResponse::Ok().finish())
}

View File

@ -106,8 +106,6 @@ impl ApubObjectType for Comment {
}
async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
let note = self.to_apub(context.pool()).await?;
let post_id = self.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
@ -117,7 +115,7 @@ impl ApubObjectType for Comment {
})
.await??;
let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?);
let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
delete
.set_context(activitystreams::context())
.set_id(generate_activity_id(DeleteType::Delete)?)
@ -133,8 +131,6 @@ impl ApubObjectType for Comment {
creator: &User_,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let note = self.to_apub(context.pool()).await?;
let post_id = self.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
@ -145,7 +141,7 @@ impl ApubObjectType for Comment {
.await??;
// Generate a fake delete activity, with the correct object
let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?);
let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
delete
.set_context(activitystreams::context())
.set_id(generate_activity_id(DeleteType::Delete)?)
@ -165,8 +161,6 @@ impl ApubObjectType for Comment {
}
async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
let note = self.to_apub(context.pool()).await?;
let post_id = self.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
@ -176,7 +170,7 @@ impl ApubObjectType for Comment {
})
.await??;
let mut remove = Remove::new(mod_.actor_id.to_owned(), note.into_any_base()?);
let mut remove = Remove::new(mod_.actor_id.to_owned(), Url::parse(&self.ap_id)?);
remove
.set_context(activitystreams::context())
.set_id(generate_activity_id(RemoveType::Remove)?)
@ -188,8 +182,6 @@ impl ApubObjectType for Comment {
}
async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
let note = self.to_apub(context.pool()).await?;
let post_id = self.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
@ -200,7 +192,7 @@ impl ApubObjectType for Comment {
.await??;
// Generate a fake delete activity, with the correct object
let mut remove = Remove::new(mod_.actor_id.to_owned(), note.into_any_base()?);
let mut remove = Remove::new(mod_.actor_id.to_owned(), Url::parse(&self.ap_id)?);
remove
.set_context(activitystreams::context())
.set_id(generate_activity_id(RemoveType::Remove)?)

View File

@ -124,9 +124,7 @@ impl ActorType for Community {
}
async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
let group = self.to_apub(context.pool()).await?;
let mut remove = Remove::new(mod_.actor_id.to_owned(), group.into_any_base()?);
let mut remove = Remove::new(mod_.actor_id.to_owned(), self.actor_id()?);
remove
.set_context(activitystreams::context())
.set_id(generate_activity_id(RemoveType::Remove)?)
@ -138,9 +136,7 @@ impl ActorType for Community {
}
async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
let group = self.to_apub(context.pool()).await?;
let mut remove = Remove::new(mod_.actor_id.to_owned(), group.into_any_base()?);
let mut remove = Remove::new(mod_.actor_id.to_owned(), self.actor_id()?);
remove
.set_context(activitystreams::context())
.set_id(generate_activity_id(RemoveType::Remove)?)

View File

@ -24,6 +24,7 @@ use lemmy_db::{community::Community, post::Post, user::User_, Crud};
use lemmy_structs::blocking;
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[async_trait::async_trait(?Send)]
impl ApubObjectType for Post {
@ -70,15 +71,13 @@ impl ApubObjectType for Post {
}
async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
let page = self.to_apub(context.pool()).await?;
let community_id = self.community_id;
let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id)
})
.await??;
let mut delete = Delete::new(creator.actor_id.to_owned(), page.into_any_base()?);
let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
delete
.set_context(activitystreams::context())
.set_id(generate_activity_id(DeleteType::Delete)?)
@ -94,15 +93,13 @@ impl ApubObjectType for Post {
creator: &User_,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let page = self.to_apub(context.pool()).await?;
let community_id = self.community_id;
let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id)
})
.await??;
let mut delete = Delete::new(creator.actor_id.to_owned(), page.into_any_base()?);
let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
delete
.set_context(activitystreams::context())
.set_id(generate_activity_id(DeleteType::Delete)?)
@ -122,15 +119,13 @@ impl ApubObjectType for Post {
}
async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
let page = self.to_apub(context.pool()).await?;
let community_id = self.community_id;
let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id)
})
.await??;
let mut remove = Remove::new(mod_.actor_id.to_owned(), page.into_any_base()?);
let mut remove = Remove::new(mod_.actor_id.to_owned(), Url::parse(&self.ap_id)?);
remove
.set_context(activitystreams::context())
.set_id(generate_activity_id(RemoveType::Remove)?)
@ -142,15 +137,13 @@ impl ApubObjectType for Post {
}
async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
let page = self.to_apub(context.pool()).await?;
let community_id = self.community_id;
let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id)
})
.await??;
let mut remove = Remove::new(mod_.actor_id.to_owned(), page.into_any_base()?);
let mut remove = Remove::new(mod_.actor_id.to_owned(), Url::parse(&self.ap_id)?);
remove
.set_context(activitystreams::context())
.set_id(generate_activity_id(RemoveType::Remove)?)

View File

@ -19,6 +19,7 @@ use lemmy_db::{private_message::PrivateMessage, user::User_, Crud};
use lemmy_structs::blocking;
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[async_trait::async_trait(?Send)]
impl ApubObjectType for PrivateMessage {
@ -58,12 +59,10 @@ impl ApubObjectType for PrivateMessage {
}
async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
let note = self.to_apub(context.pool()).await?;
let recipient_id = self.recipient_id;
let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?);
let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
delete
.set_context(activitystreams::context())
.set_id(generate_activity_id(DeleteType::Delete)?)
@ -78,12 +77,10 @@ impl ApubObjectType for PrivateMessage {
creator: &User_,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let note = self.to_apub(context.pool()).await?;
let recipient_id = self.recipient_id;
let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?);
let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?);
delete
.set_context(activitystreams::context())
.set_id(generate_activity_id(DeleteType::Delete)?)

View File

@ -8,6 +8,7 @@ use crate::{
use activitystreams::{
activity::{Accept, ActorAndObject, Create, Delete, Undo, Update},
base::AnyBase,
error::DomainError,
object::Note,
prelude::*,
};
@ -15,7 +16,6 @@ use actix_web::{web, HttpRequest, HttpResponse};
use anyhow::Context;
use lemmy_db::{
community::{CommunityFollower, CommunityFollowerForm},
naive_now,
private_message::{PrivateMessage, PrivateMessageForm},
private_message_view::PrivateMessageView,
user::User_,
@ -131,7 +131,17 @@ async fn receive_create_private_message(
)?
.context(location_info!())?;
let domain = Some(create.id_unchecked().context(location_info!())?.to_owned());
let actor = create
.actor()?
.to_owned()
.single_xsd_any_uri()
.context(location_info!())?;
let domain = Some(
create
.id(actor.domain().context(location_info!())?)?
.context(location_info!())?
.to_owned(),
);
let private_message = PrivateMessageForm::from_apub(&note, context, domain).await?;
let inserted_private_message = blocking(&context.pool(), move |conn| {
@ -172,7 +182,17 @@ async fn receive_update_private_message(
)?
.context(location_info!())?;
let domain = Some(update.id_unchecked().context(location_info!())?.to_owned());
let actor = update
.actor()?
.to_owned()
.single_xsd_any_uri()
.context(location_info!())?;
let domain = Some(
update
.id(actor.domain().context(location_info!())?)?
.context(location_info!())?
.to_owned(),
);
let private_message_form = PrivateMessageForm::from_apub(&note, context, domain).await?;
let private_message_ap_id = private_message_form
@ -216,52 +236,39 @@ async fn receive_delete_private_message(
context: &LemmyContext,
) -> Result<HttpResponse, LemmyError> {
let delete = Delete::from_any_base(activity)?.context(location_info!())?;
let note = Note::from_any_base(
delete
.object()
.as_one()
.context(location_info!())?
.to_owned(),
)?
.context(location_info!())?;
let domain = Some(delete.id_unchecked().context(location_info!())?.to_owned());
let private_message_form = PrivateMessageForm::from_apub(&note, context, domain).await?;
let private_message_ap_id = private_message_form.ap_id.context(location_info!())?;
let private_message = blocking(&context.pool(), move |conn| {
PrivateMessage::read_from_apub_id(conn, &private_message_ap_id)
let private_message_id = delete
.object()
.to_owned()
.single_xsd_any_uri()
.context(location_info!())?;
let actor = delete
.actor()?
.to_owned()
.single_xsd_any_uri()
.context(location_info!())?;
let delete_id = delete
.id(actor.domain().context(location_info!())?)?
.map(|i| i.domain())
.flatten();
if private_message_id.domain() != delete_id {
return Err(DomainError.into());
}
let private_message = blocking(context.pool(), move |conn| {
PrivateMessage::read_from_apub_id(conn, private_message_id.as_str())
})
.await??;
let deleted_private_message = blocking(context.pool(), move |conn| {
PrivateMessage::update_deleted(conn, private_message.id, true)
})
.await??;
let private_message_form = PrivateMessageForm {
content: private_message_form.content,
recipient_id: private_message.recipient_id,
creator_id: private_message.creator_id,
deleted: Some(true),
read: None,
ap_id: Some(private_message.ap_id),
local: private_message.local,
published: None,
updated: Some(naive_now()),
};
let private_message_id = private_message.id;
blocking(&context.pool(), move |conn| {
PrivateMessage::update(conn, private_message_id, &private_message_form)
})
.await??;
let private_message_id = private_message.id;
let message = blocking(&context.pool(), move |conn| {
PrivateMessageView::read(&conn, private_message_id)
PrivateMessageView::read(&conn, deleted_private_message.id)
})
.await??;
let res = PrivateMessageResponse { message };
let recipient_id = res.message.recipient_id;
context.chat_server().do_send(SendUserRoomMessage {
op: UserOperation::EditPrivateMessage,
response: res,
@ -279,47 +286,35 @@ async fn receive_undo_delete_private_message(
let undo = Undo::from_any_base(activity)?.context(location_info!())?;
let delete = Delete::from_any_base(undo.object().as_one().context(location_info!())?.to_owned())?
.context(location_info!())?;
let note = Note::from_any_base(
delete
.object()
.as_one()
.context(location_info!())?
.to_owned(),
)?
.context(location_info!())?;
let private_message_id = delete
.object()
.to_owned()
.single_xsd_any_uri()
.context(location_info!())?;
let actor = undo
.actor()?
.to_owned()
.single_xsd_any_uri()
.context(location_info!())?;
let undo_id = undo
.id(actor.domain().context(location_info!())?)?
.map(|i| i.domain())
.flatten();
if private_message_id.domain() != undo_id {
return Err(DomainError.into());
}
let domain = Some(undo.id_unchecked().context(location_info!())?.to_owned());
let private_message = PrivateMessageForm::from_apub(&note, context, domain).await?;
let private_message_ap_id = private_message
.ap_id
.as_ref()
.context(location_info!())?
.clone();
let private_message_id = blocking(&context.pool(), move |conn| {
PrivateMessage::read_from_apub_id(conn, &private_message_ap_id).map(|pm| pm.id)
let private_message = blocking(context.pool(), move |conn| {
PrivateMessage::read_from_apub_id(conn, private_message_id.as_str())
})
.await??;
let private_message_form = PrivateMessageForm {
content: private_message.content,
recipient_id: private_message.recipient_id,
creator_id: private_message.creator_id,
deleted: Some(false),
read: None,
ap_id: private_message.ap_id,
local: private_message.local,
published: None,
updated: Some(naive_now()),
};
blocking(&context.pool(), move |conn| {
PrivateMessage::update(conn, private_message_id, &private_message_form)
let deleted_private_message = blocking(context.pool(), move |conn| {
PrivateMessage::update_deleted(conn, private_message.id, false)
})
.await??;
let message = blocking(&context.pool(), move |conn| {
PrivateMessageView::read(&conn, private_message_id)
PrivateMessageView::read(&conn, deleted_private_message.id)
})
.await??;