Rewrite delete activities (#1699)
* Limit type/method visibility in apub code * Simplify db_queries traits by removing generics * Simplify delete activity implementation * Rewrite delete activities * Implement helper functions for websocket message sending * When receiving delete reason as empty string, change to none
This commit is contained in:
parent
6fbf6a684c
commit
28d6370c35
65 changed files with 1170 additions and 1620 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1944,6 +1944,8 @@ dependencies = [
|
||||||
"lemmy_api_common",
|
"lemmy_api_common",
|
||||||
"lemmy_db_queries",
|
"lemmy_db_queries",
|
||||||
"lemmy_db_schema",
|
"lemmy_db_schema",
|
||||||
|
"lemmy_db_views",
|
||||||
|
"lemmy_db_views_actor",
|
||||||
"lemmy_utils",
|
"lemmy_utils",
|
||||||
"log",
|
"log",
|
||||||
"rand 0.8.4",
|
"rand 0.8.4",
|
||||||
|
|
|
@ -18,7 +18,7 @@ use lemmy_db_queries::{source::comment::Comment_, Likeable, Saveable};
|
||||||
use lemmy_db_schema::{source::comment::*, LocalUserId};
|
use lemmy_db_schema::{source::comment::*, LocalUserId};
|
||||||
use lemmy_db_views::{comment_view::CommentView, local_user_view::LocalUserView};
|
use lemmy_db_views::{comment_view::CommentView, local_user_view::LocalUserView};
|
||||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{messages::SendComment, LemmyContext, UserOperation};
|
use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperation};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
|
@ -206,26 +206,15 @@ impl Perform for CreateCommentLike {
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Have to refetch the comment to get the current state
|
send_comment_ws_message(
|
||||||
let comment_id = data.comment_id;
|
data.comment_id,
|
||||||
let person_id = local_user_view.person.id;
|
UserOperation::CreateCommentLike,
|
||||||
let liked_comment = blocking(context.pool(), move |conn| {
|
|
||||||
CommentView::read(conn, comment_id, Some(person_id))
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
let res = CommentResponse {
|
|
||||||
comment_view: liked_comment,
|
|
||||||
recipient_ids,
|
|
||||||
form_id: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
context.chat_server().do_send(SendComment {
|
|
||||||
op: UserOperation::CreateCommentLike,
|
|
||||||
comment: res.clone(),
|
|
||||||
websocket_id,
|
websocket_id,
|
||||||
});
|
None,
|
||||||
|
Some(local_user_view.person.id),
|
||||||
Ok(res)
|
recipient_ids,
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ use lemmy_db_queries::{source::post::Post_, Crud, Likeable, Saveable};
|
||||||
use lemmy_db_schema::source::{moderator::*, post::*};
|
use lemmy_db_schema::source::{moderator::*, post::*};
|
||||||
use lemmy_db_views::post_view::PostView;
|
use lemmy_db_views::post_view::PostView;
|
||||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{messages::SendPost, LemmyContext, UserOperation};
|
use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperation};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
|
@ -96,23 +96,14 @@ impl Perform for CreatePostLike {
|
||||||
// Mark the post as read
|
// Mark the post as read
|
||||||
mark_post_as_read(person_id, post_id, context.pool()).await?;
|
mark_post_as_read(person_id, post_id, context.pool()).await?;
|
||||||
|
|
||||||
let post_id = data.post_id;
|
send_post_ws_message(
|
||||||
let person_id = local_user_view.person.id;
|
data.post_id,
|
||||||
let post_view = blocking(context.pool(), move |conn| {
|
UserOperation::CreatePostLike,
|
||||||
PostView::read(conn, post_id, Some(person_id))
|
|
||||||
})
|
|
||||||
.await?
|
|
||||||
.map_err(|_| ApiError::err("couldnt_find_post"))?;
|
|
||||||
|
|
||||||
let res = PostResponse { post_view };
|
|
||||||
|
|
||||||
context.chat_server().do_send(SendPost {
|
|
||||||
op: UserOperation::CreatePostLike,
|
|
||||||
post: res.clone(),
|
|
||||||
websocket_id,
|
websocket_id,
|
||||||
});
|
Some(local_user_view.person.id),
|
||||||
|
context,
|
||||||
Ok(res)
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,22 +162,14 @@ impl Perform for LockPost {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Refetch the post
|
send_post_ws_message(
|
||||||
let post_id = data.post_id;
|
data.post_id,
|
||||||
let post_view = blocking(context.pool(), move |conn| {
|
UserOperation::LockPost,
|
||||||
PostView::read(conn, post_id, Some(local_user_view.person.id))
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
let res = PostResponse { post_view };
|
|
||||||
|
|
||||||
context.chat_server().do_send(SendPost {
|
|
||||||
op: UserOperation::LockPost,
|
|
||||||
post: res.clone(),
|
|
||||||
websocket_id,
|
websocket_id,
|
||||||
});
|
Some(local_user_view.person.id),
|
||||||
|
context,
|
||||||
Ok(res)
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,22 +232,14 @@ impl Perform for StickyPost {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Refetch the post
|
send_post_ws_message(
|
||||||
let post_id = data.post_id;
|
data.post_id,
|
||||||
let post_view = blocking(context.pool(), move |conn| {
|
UserOperation::StickyPost,
|
||||||
PostView::read(conn, post_id, Some(local_user_view.person.id))
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
let res = PostResponse { post_view };
|
|
||||||
|
|
||||||
context.chat_server().do_send(SendPost {
|
|
||||||
op: UserOperation::StickyPost,
|
|
||||||
post: res.clone(),
|
|
||||||
websocket_id,
|
websocket_id,
|
||||||
});
|
Some(local_user_view.person.id),
|
||||||
|
context,
|
||||||
Ok(res)
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,8 @@ use lemmy_api_common::{
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud};
|
use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud};
|
||||||
use lemmy_db_schema::source::private_message::PrivateMessage;
|
use lemmy_db_schema::source::private_message::PrivateMessage;
|
||||||
use lemmy_db_views::{local_user_view::LocalUserView, private_message_view::PrivateMessageView};
|
|
||||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperation};
|
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperation};
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl Perform for MarkPrivateMessageAsRead {
|
impl Perform for MarkPrivateMessageAsRead {
|
||||||
|
@ -43,32 +42,7 @@ impl Perform for MarkPrivateMessageAsRead {
|
||||||
.map_err(|_| ApiError::err("couldnt_update_private_message"))?;
|
.map_err(|_| ApiError::err("couldnt_update_private_message"))?;
|
||||||
|
|
||||||
// No need to send an apub update
|
// No need to send an apub update
|
||||||
let private_message_id = data.private_message_id;
|
let op = UserOperation::MarkPrivateMessageAsRead;
|
||||||
let private_message_view = blocking(context.pool(), move |conn| {
|
send_pm_ws_message(data.private_message_id, op, websocket_id, context).await
|
||||||
PrivateMessageView::read(conn, private_message_id)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
let res = PrivateMessageResponse {
|
|
||||||
private_message_view,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Send notifications to the local recipient, if one exists
|
|
||||||
let recipient_id = orig_private_message.recipient_id;
|
|
||||||
if let Ok(local_recipient) = blocking(context.pool(), move |conn| {
|
|
||||||
LocalUserView::read_person(conn, recipient_id)
|
|
||||||
})
|
|
||||||
.await?
|
|
||||||
{
|
|
||||||
let local_recipient_id = local_recipient.local_user.id;
|
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
|
||||||
op: UserOperation::MarkPrivateMessageAsRead,
|
|
||||||
response: res.clone(),
|
|
||||||
local_recipient_id,
|
|
||||||
websocket_id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(res)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,13 @@ use lemmy_apub::{
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::comment::Comment_, Crud, Likeable};
|
use lemmy_db_queries::{source::comment::Comment_, Crud, Likeable};
|
||||||
use lemmy_db_schema::source::comment::*;
|
use lemmy_db_schema::source::comment::*;
|
||||||
use lemmy_db_views::comment_view::CommentView;
|
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
utils::{remove_slurs, scrape_text_for_mentions},
|
utils::{remove_slurs, scrape_text_for_mentions},
|
||||||
ApiError,
|
ApiError,
|
||||||
ConnectionId,
|
ConnectionId,
|
||||||
LemmyError,
|
LemmyError,
|
||||||
};
|
};
|
||||||
use lemmy_websocket::{messages::SendComment, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl PerformCrud for CreateComment {
|
impl PerformCrud for CreateComment {
|
||||||
|
@ -137,37 +136,25 @@ impl PerformCrud for CreateComment {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let person_id = local_user_view.person.id;
|
|
||||||
let mut comment_view = blocking(context.pool(), move |conn| {
|
|
||||||
CommentView::read(conn, inserted_comment.id, Some(person_id))
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
// If its a comment to yourself, mark it as read
|
// If its a comment to yourself, mark it as read
|
||||||
let comment_id = comment_view.comment.id;
|
if local_user_view.person.id == inserted_comment.creator_id {
|
||||||
if local_user_view.person.id == comment_view.get_recipient_id() {
|
let comment_id = inserted_comment.id;
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
Comment::update_read(conn, comment_id, true)
|
Comment::update_read(conn, comment_id, true)
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
.map_err(|_| ApiError::err("couldnt_update_comment"))?;
|
.map_err(|_| ApiError::err("couldnt_update_comment"))?;
|
||||||
comment_view.comment.read = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut res = CommentResponse {
|
send_comment_ws_message(
|
||||||
comment_view,
|
inserted_comment.id,
|
||||||
recipient_ids,
|
UserOperationCrud::CreateComment,
|
||||||
form_id: data.form_id.to_owned(),
|
|
||||||
};
|
|
||||||
|
|
||||||
context.chat_server().do_send(SendComment {
|
|
||||||
op: UserOperationCrud::CreateComment,
|
|
||||||
comment: res.clone(),
|
|
||||||
websocket_id,
|
websocket_id,
|
||||||
});
|
data.form_id.to_owned(),
|
||||||
|
Some(local_user_view.person.id),
|
||||||
res.recipient_ids = Vec::new(); // Necessary to avoid doubles
|
recipient_ids,
|
||||||
|
context,
|
||||||
Ok(res)
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,12 @@ use lemmy_api_common::{
|
||||||
is_mod_or_admin,
|
is_mod_or_admin,
|
||||||
send_local_notifs,
|
send_local_notifs,
|
||||||
};
|
};
|
||||||
use lemmy_apub::ApubObjectType;
|
use lemmy_apub::activities::deletion::{send_apub_delete, send_apub_remove};
|
||||||
use lemmy_db_queries::{source::comment::Comment_, Crud, DeleteableOrRemoveable};
|
use lemmy_db_queries::{source::comment::Comment_, Crud};
|
||||||
use lemmy_db_schema::source::{comment::*, moderator::*};
|
use lemmy_db_schema::source::{comment::*, community::Community, moderator::*, post::Post};
|
||||||
use lemmy_db_views::comment_view::CommentView;
|
use lemmy_db_views::comment_view::CommentView;
|
||||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{messages::SendComment, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl PerformCrud for DeleteComment {
|
impl PerformCrud for DeleteComment {
|
||||||
|
@ -47,63 +47,48 @@ impl PerformCrud for DeleteComment {
|
||||||
|
|
||||||
// Do the delete
|
// Do the delete
|
||||||
let deleted = data.deleted;
|
let deleted = data.deleted;
|
||||||
let mut updated_comment = blocking(context.pool(), move |conn| {
|
let updated_comment = blocking(context.pool(), move |conn| {
|
||||||
Comment::update_deleted(conn, comment_id, deleted)
|
Comment::update_deleted(conn, comment_id, deleted)
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
.map_err(|_| ApiError::err("couldnt_update_comment"))?;
|
.map_err(|_| ApiError::err("couldnt_update_comment"))?;
|
||||||
|
|
||||||
// Send the apub message
|
// Send the apub message
|
||||||
if deleted {
|
let community = blocking(context.pool(), move |conn| {
|
||||||
updated_comment = updated_comment.blank_out_deleted_or_removed_info();
|
Community::read(conn, orig_comment.post.community_id)
|
||||||
updated_comment
|
|
||||||
.send_delete(&local_user_view.person, context)
|
|
||||||
.await?;
|
|
||||||
} else {
|
|
||||||
updated_comment
|
|
||||||
.send_undo_delete(&local_user_view.person, context)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refetch it
|
|
||||||
let comment_id = data.comment_id;
|
|
||||||
let person_id = local_user_view.person.id;
|
|
||||||
let mut comment_view = blocking(context.pool(), move |conn| {
|
|
||||||
CommentView::read(conn, comment_id, Some(person_id))
|
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
send_apub_delete(
|
||||||
|
&local_user_view.person,
|
||||||
|
&community,
|
||||||
|
updated_comment.ap_id.clone().into(),
|
||||||
|
deleted,
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Blank out deleted or removed info
|
let post_id = updated_comment.post_id;
|
||||||
if deleted {
|
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
comment_view.comment = comment_view.comment.blank_out_deleted_or_removed_info();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the recipients
|
|
||||||
let comment_view_2 = comment_view.clone();
|
|
||||||
let mentions = vec![];
|
|
||||||
let recipient_ids = send_local_notifs(
|
let recipient_ids = send_local_notifs(
|
||||||
mentions,
|
vec![],
|
||||||
updated_comment,
|
updated_comment,
|
||||||
local_user_view.person.clone(),
|
local_user_view.person.clone(),
|
||||||
comment_view_2.post,
|
post,
|
||||||
context.pool(),
|
context.pool(),
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let res = CommentResponse {
|
send_comment_ws_message(
|
||||||
comment_view,
|
data.comment_id,
|
||||||
recipient_ids,
|
UserOperationCrud::DeleteComment,
|
||||||
form_id: None, // TODO a comment delete might clear forms?
|
|
||||||
};
|
|
||||||
|
|
||||||
context.chat_server().do_send(SendComment {
|
|
||||||
op: UserOperationCrud::DeleteComment,
|
|
||||||
comment: res.clone(),
|
|
||||||
websocket_id,
|
websocket_id,
|
||||||
});
|
None, // TODO a comment delete might clear forms?
|
||||||
|
Some(local_user_view.person.id),
|
||||||
Ok(res)
|
recipient_ids,
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +127,7 @@ impl PerformCrud for RemoveComment {
|
||||||
|
|
||||||
// Do the remove
|
// Do the remove
|
||||||
let removed = data.removed;
|
let removed = data.removed;
|
||||||
let mut updated_comment = blocking(context.pool(), move |conn| {
|
let updated_comment = blocking(context.pool(), move |conn| {
|
||||||
Comment::update_removed(conn, comment_id, removed)
|
Comment::update_removed(conn, comment_id, removed)
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
|
@ -161,56 +146,41 @@ impl PerformCrud for RemoveComment {
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
// Send the apub message
|
// Send the apub message
|
||||||
if removed {
|
let community = blocking(context.pool(), move |conn| {
|
||||||
updated_comment = updated_comment.blank_out_deleted_or_removed_info();
|
Community::read(conn, orig_comment.post.community_id)
|
||||||
updated_comment
|
|
||||||
.send_remove(&local_user_view.person, context)
|
|
||||||
.await?;
|
|
||||||
} else {
|
|
||||||
updated_comment
|
|
||||||
.send_undo_remove(&local_user_view.person, context)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refetch it
|
|
||||||
let comment_id = data.comment_id;
|
|
||||||
let person_id = local_user_view.person.id;
|
|
||||||
let mut comment_view = blocking(context.pool(), move |conn| {
|
|
||||||
CommentView::read(conn, comment_id, Some(person_id))
|
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
send_apub_remove(
|
||||||
|
&local_user_view.person,
|
||||||
|
&community,
|
||||||
|
updated_comment.ap_id.clone().into(),
|
||||||
|
data.reason.clone().unwrap_or_else(|| "".to_string()),
|
||||||
|
removed,
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Blank out deleted or removed info
|
let post_id = updated_comment.post_id;
|
||||||
if removed {
|
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
comment_view.comment = comment_view.comment.blank_out_deleted_or_removed_info();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the recipients
|
|
||||||
let comment_view_2 = comment_view.clone();
|
|
||||||
|
|
||||||
let mentions = vec![];
|
|
||||||
let recipient_ids = send_local_notifs(
|
let recipient_ids = send_local_notifs(
|
||||||
mentions,
|
vec![],
|
||||||
updated_comment,
|
updated_comment,
|
||||||
local_user_view.person.clone(),
|
local_user_view.person.clone(),
|
||||||
comment_view_2.post,
|
post,
|
||||||
context.pool(),
|
context.pool(),
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let res = CommentResponse {
|
send_comment_ws_message(
|
||||||
comment_view,
|
data.comment_id,
|
||||||
recipient_ids,
|
UserOperationCrud::RemoveComment,
|
||||||
form_id: None, // TODO maybe this might clear other forms
|
|
||||||
};
|
|
||||||
|
|
||||||
context.chat_server().do_send(SendComment {
|
|
||||||
op: UserOperationCrud::RemoveComment,
|
|
||||||
comment: res.clone(),
|
|
||||||
websocket_id,
|
websocket_id,
|
||||||
});
|
None, // TODO maybe this might clear other forms
|
||||||
|
Some(local_user_view.person.id),
|
||||||
Ok(res)
|
recipient_ids,
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use lemmy_apub::activities::{
|
||||||
comment::create_or_update::CreateOrUpdateComment,
|
comment::create_or_update::CreateOrUpdateComment,
|
||||||
CreateOrUpdateType,
|
CreateOrUpdateType,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::comment::Comment_, DeleteableOrRemoveable};
|
use lemmy_db_queries::source::comment::Comment_;
|
||||||
use lemmy_db_schema::source::comment::*;
|
use lemmy_db_schema::source::comment::*;
|
||||||
use lemmy_db_views::comment_view::CommentView;
|
use lemmy_db_views::comment_view::CommentView;
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
|
@ -20,7 +20,7 @@ use lemmy_utils::{
|
||||||
ConnectionId,
|
ConnectionId,
|
||||||
LemmyError,
|
LemmyError,
|
||||||
};
|
};
|
||||||
use lemmy_websocket::{messages::SendComment, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl PerformCrud for EditComment {
|
impl PerformCrud for EditComment {
|
||||||
|
@ -83,30 +83,15 @@ impl PerformCrud for EditComment {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let comment_id = data.comment_id;
|
send_comment_ws_message(
|
||||||
let person_id = local_user_view.person.id;
|
data.comment_id,
|
||||||
let mut comment_view = blocking(context.pool(), move |conn| {
|
UserOperationCrud::EditComment,
|
||||||
CommentView::read(conn, comment_id, Some(person_id))
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
// Blank out deleted or removed info
|
|
||||||
if comment_view.comment.deleted || comment_view.comment.removed {
|
|
||||||
comment_view.comment = comment_view.comment.blank_out_deleted_or_removed_info();
|
|
||||||
}
|
|
||||||
|
|
||||||
let res = CommentResponse {
|
|
||||||
comment_view,
|
|
||||||
recipient_ids,
|
|
||||||
form_id: data.form_id.to_owned(),
|
|
||||||
};
|
|
||||||
|
|
||||||
context.chat_server().do_send(SendComment {
|
|
||||||
op: UserOperationCrud::EditComment,
|
|
||||||
comment: res.clone(),
|
|
||||||
websocket_id,
|
websocket_id,
|
||||||
});
|
data.form_id.to_owned(),
|
||||||
|
None,
|
||||||
Ok(res)
|
recipient_ids,
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
use crate::{community::send_community_websocket, PerformCrud};
|
use crate::PerformCrud;
|
||||||
use actix_web::web::Data;
|
use actix_web::web::Data;
|
||||||
use lemmy_api_common::{blocking, community::*, get_local_user_view_from_jwt, is_admin};
|
use lemmy_api_common::{blocking, community::*, get_local_user_view_from_jwt, is_admin};
|
||||||
use lemmy_apub::CommunityType;
|
use lemmy_apub::activities::deletion::{send_apub_delete, send_apub_remove};
|
||||||
use lemmy_db_queries::{source::community::Community_, Crud, DeleteableOrRemoveable};
|
use lemmy_db_queries::{source::community::Community_, Crud};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
community::*,
|
community::*,
|
||||||
moderator::{ModRemoveCommunity, ModRemoveCommunityForm},
|
moderator::{ModRemoveCommunity, ModRemoveCommunityForm},
|
||||||
};
|
};
|
||||||
use lemmy_db_views_actor::{
|
use lemmy_db_views_actor::community_moderator_view::CommunityModeratorView;
|
||||||
community_moderator_view::CommunityModeratorView,
|
|
||||||
community_view::CommunityView,
|
|
||||||
};
|
|
||||||
use lemmy_utils::{utils::naive_from_unix, ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{utils::naive_from_unix, ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud};
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl PerformCrud for DeleteCommunity {
|
impl PerformCrud for DeleteCommunity {
|
||||||
|
@ -48,39 +45,23 @@ impl PerformCrud for DeleteCommunity {
|
||||||
.map_err(|_| ApiError::err("couldnt_update_community"))?;
|
.map_err(|_| ApiError::err("couldnt_update_community"))?;
|
||||||
|
|
||||||
// Send apub messages
|
// Send apub messages
|
||||||
if deleted {
|
send_apub_delete(
|
||||||
updated_community
|
&local_user_view.person,
|
||||||
.blank_out_deleted_or_removed_info()
|
&updated_community,
|
||||||
.send_delete(local_user_view.person.to_owned(), context)
|
updated_community.actor_id.clone().into(),
|
||||||
.await?;
|
deleted,
|
||||||
} else {
|
|
||||||
updated_community
|
|
||||||
.send_undo_delete(local_user_view.person.to_owned(), context)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let community_id = data.community_id;
|
|
||||||
let person_id = local_user_view.person.id;
|
|
||||||
let mut community_view = blocking(context.pool(), move |conn| {
|
|
||||||
CommunityView::read(conn, community_id, Some(person_id))
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
// Blank out deleted or removed info
|
|
||||||
if deleted {
|
|
||||||
community_view.community = community_view.community.blank_out_deleted_or_removed_info();
|
|
||||||
}
|
|
||||||
|
|
||||||
let res = CommunityResponse { community_view };
|
|
||||||
|
|
||||||
send_community_websocket(
|
|
||||||
&res,
|
|
||||||
context,
|
context,
|
||||||
websocket_id,
|
)
|
||||||
UserOperationCrud::DeleteCommunity,
|
.await?;
|
||||||
);
|
|
||||||
|
|
||||||
Ok(res)
|
send_community_ws_message(
|
||||||
|
data.community_id,
|
||||||
|
UserOperationCrud::DeleteCommunity,
|
||||||
|
websocket_id,
|
||||||
|
Some(local_user_view.person.id),
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,36 +104,23 @@ impl PerformCrud for RemoveCommunity {
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
// Apub messages
|
// Apub messages
|
||||||
if removed {
|
send_apub_remove(
|
||||||
updated_community
|
&local_user_view.person,
|
||||||
.blank_out_deleted_or_removed_info()
|
&updated_community,
|
||||||
.send_remove(context)
|
updated_community.actor_id.clone().into(),
|
||||||
.await?;
|
data.reason.clone().unwrap_or_else(|| "".to_string()),
|
||||||
} else {
|
removed,
|
||||||
updated_community.send_undo_remove(context).await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let community_id = data.community_id;
|
|
||||||
let person_id = local_user_view.person.id;
|
|
||||||
let mut community_view = blocking(context.pool(), move |conn| {
|
|
||||||
CommunityView::read(conn, community_id, Some(person_id))
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
// Blank out deleted or removed info
|
|
||||||
if removed {
|
|
||||||
community_view.community = community_view.community.blank_out_deleted_or_removed_info();
|
|
||||||
}
|
|
||||||
|
|
||||||
let res = CommunityResponse { community_view };
|
|
||||||
|
|
||||||
send_community_websocket(
|
|
||||||
&res,
|
|
||||||
context,
|
context,
|
||||||
websocket_id,
|
)
|
||||||
UserOperationCrud::RemoveCommunity,
|
.await?;
|
||||||
);
|
|
||||||
|
|
||||||
Ok(res)
|
send_community_ws_message(
|
||||||
|
data.community_id,
|
||||||
|
UserOperationCrud::RemoveCommunity,
|
||||||
|
websocket_id,
|
||||||
|
Some(local_user_view.person.id),
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,4 @@
|
||||||
use actix_web::web::Data;
|
|
||||||
use lemmy_api_common::community::CommunityResponse;
|
|
||||||
use lemmy_utils::ConnectionId;
|
|
||||||
use lemmy_websocket::{messages::SendCommunityRoomMessage, LemmyContext, UserOperationCrud};
|
|
||||||
|
|
||||||
mod create;
|
mod create;
|
||||||
mod delete;
|
mod delete;
|
||||||
mod read;
|
mod read;
|
||||||
mod update;
|
mod update;
|
||||||
|
|
||||||
pub(in crate::community) fn send_community_websocket(
|
|
||||||
res: &CommunityResponse,
|
|
||||||
context: &Data<LemmyContext>,
|
|
||||||
websocket_id: Option<ConnectionId>,
|
|
||||||
op: UserOperationCrud,
|
|
||||||
) {
|
|
||||||
// Strip out the person id and subscribed when sending to others
|
|
||||||
let mut res_sent = res.clone();
|
|
||||||
res_sent.community_view.subscribed = false;
|
|
||||||
|
|
||||||
context.chat_server().do_send(SendCommunityRoomMessage {
|
|
||||||
op,
|
|
||||||
response: res_sent,
|
|
||||||
community_id: res.community_view.community.id,
|
|
||||||
websocket_id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{community::send_community_websocket, PerformCrud};
|
use crate::PerformCrud;
|
||||||
use actix_web::web::Data;
|
use actix_web::web::Data;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
blocking,
|
blocking,
|
||||||
|
@ -6,18 +6,15 @@ use lemmy_api_common::{
|
||||||
get_local_user_view_from_jwt,
|
get_local_user_view_from_jwt,
|
||||||
};
|
};
|
||||||
use lemmy_apub::CommunityType;
|
use lemmy_apub::CommunityType;
|
||||||
use lemmy_db_queries::{diesel_option_overwrite_to_url, Crud, DeleteableOrRemoveable};
|
use lemmy_db_queries::{diesel_option_overwrite_to_url, Crud};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
naive_now,
|
naive_now,
|
||||||
source::community::{Community, CommunityForm},
|
source::community::{Community, CommunityForm},
|
||||||
PersonId,
|
PersonId,
|
||||||
};
|
};
|
||||||
use lemmy_db_views_actor::{
|
use lemmy_db_views_actor::community_moderator_view::CommunityModeratorView;
|
||||||
community_moderator_view::CommunityModeratorView,
|
|
||||||
community_view::CommunityView,
|
|
||||||
};
|
|
||||||
use lemmy_utils::{utils::check_slurs_opt, ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{utils::check_slurs_opt, ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud};
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl PerformCrud for EditCommunity {
|
impl PerformCrud for EditCommunity {
|
||||||
|
@ -76,27 +73,7 @@ impl PerformCrud for EditCommunity {
|
||||||
.send_update(local_user_view.person.to_owned(), context)
|
.send_update(local_user_view.person.to_owned(), context)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let community_id = data.community_id;
|
let op = UserOperationCrud::EditCommunity;
|
||||||
let person_id = local_user_view.person.id;
|
send_community_ws_message(data.community_id, op, websocket_id, None, context).await
|
||||||
let mut community_view = blocking(context.pool(), move |conn| {
|
|
||||||
CommunityView::read(conn, community_id, Some(person_id))
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
// 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 res = CommunityResponse { community_view };
|
|
||||||
|
|
||||||
send_community_websocket(
|
|
||||||
&res,
|
|
||||||
context,
|
|
||||||
websocket_id,
|
|
||||||
UserOperationCrud::EditCommunity,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(res)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ use lemmy_apub::{
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::post::Post_, Crud, Likeable};
|
use lemmy_db_queries::{source::post::Post_, Crud, Likeable};
|
||||||
use lemmy_db_schema::source::post::*;
|
use lemmy_db_schema::source::post::*;
|
||||||
use lemmy_db_views::post_view::PostView;
|
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
request::fetch_iframely_and_pictrs_data,
|
request::fetch_iframely_and_pictrs_data,
|
||||||
utils::{check_slurs, check_slurs_opt, clean_url_params, is_valid_post_title},
|
utils::{check_slurs, check_slurs_opt, clean_url_params, is_valid_post_title},
|
||||||
|
@ -27,7 +26,7 @@ use lemmy_utils::{
|
||||||
ConnectionId,
|
ConnectionId,
|
||||||
LemmyError,
|
LemmyError,
|
||||||
};
|
};
|
||||||
use lemmy_websocket::{messages::SendPost, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl PerformCrud for CreatePost {
|
impl PerformCrud for CreatePost {
|
||||||
|
@ -129,22 +128,13 @@ impl PerformCrud for CreatePost {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Refetch the view
|
send_post_ws_message(
|
||||||
let inserted_post_id = inserted_post.id;
|
inserted_post.id,
|
||||||
let post_view = blocking(context.pool(), move |conn| {
|
UserOperationCrud::CreatePost,
|
||||||
PostView::read(conn, inserted_post_id, Some(local_user_view.person.id))
|
|
||||||
})
|
|
||||||
.await?
|
|
||||||
.map_err(|_| ApiError::err("couldnt_find_post"))?;
|
|
||||||
|
|
||||||
let res = PostResponse { post_view };
|
|
||||||
|
|
||||||
context.chat_server().do_send(SendPost {
|
|
||||||
op: UserOperationCrud::CreatePost,
|
|
||||||
post: res.clone(),
|
|
||||||
websocket_id,
|
websocket_id,
|
||||||
});
|
Some(local_user_view.person.id),
|
||||||
|
context,
|
||||||
Ok(res)
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,11 @@ use lemmy_api_common::{
|
||||||
is_mod_or_admin,
|
is_mod_or_admin,
|
||||||
post::*,
|
post::*,
|
||||||
};
|
};
|
||||||
use lemmy_apub::ApubObjectType;
|
use lemmy_apub::activities::deletion::{send_apub_delete, send_apub_remove};
|
||||||
use lemmy_db_queries::{source::post::Post_, Crud, DeleteableOrRemoveable};
|
use lemmy_db_queries::{source::post::Post_, Crud};
|
||||||
use lemmy_db_schema::source::{moderator::*, post::*};
|
use lemmy_db_schema::source::{community::Community, moderator::*, post::*};
|
||||||
use lemmy_db_views::post_view::PostView;
|
|
||||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{messages::SendPost, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl PerformCrud for DeletePost {
|
impl PerformCrud for DeletePost {
|
||||||
|
@ -50,37 +49,27 @@ impl PerformCrud for DeletePost {
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
// apub updates
|
// apub updates
|
||||||
if deleted {
|
let community = blocking(context.pool(), move |conn| {
|
||||||
updated_post
|
Community::read(conn, orig_post.community_id)
|
||||||
.blank_out_deleted_or_removed_info()
|
|
||||||
.send_delete(&local_user_view.person, context)
|
|
||||||
.await?;
|
|
||||||
} else {
|
|
||||||
updated_post
|
|
||||||
.send_undo_delete(&local_user_view.person, context)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refetch the post
|
|
||||||
let post_id = data.post_id;
|
|
||||||
let mut post_view = blocking(context.pool(), move |conn| {
|
|
||||||
PostView::read(conn, post_id, Some(local_user_view.person.id))
|
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
send_apub_delete(
|
||||||
|
&local_user_view.person,
|
||||||
|
&community,
|
||||||
|
updated_post.ap_id.into(),
|
||||||
|
deleted,
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
if deleted {
|
send_post_ws_message(
|
||||||
post_view.post = post_view.post.blank_out_deleted_or_removed_info();
|
data.post_id,
|
||||||
}
|
UserOperationCrud::DeletePost,
|
||||||
|
|
||||||
let res = PostResponse { post_view };
|
|
||||||
|
|
||||||
context.chat_server().do_send(SendPost {
|
|
||||||
op: UserOperationCrud::DeletePost,
|
|
||||||
post: res.clone(),
|
|
||||||
websocket_id,
|
websocket_id,
|
||||||
});
|
Some(local_user_view.person.id),
|
||||||
|
context,
|
||||||
Ok(res)
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,38 +124,27 @@ impl PerformCrud for RemovePost {
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
// apub updates
|
// apub updates
|
||||||
if removed {
|
let community = blocking(context.pool(), move |conn| {
|
||||||
updated_post
|
Community::read(conn, orig_post.community_id)
|
||||||
.blank_out_deleted_or_removed_info()
|
|
||||||
.send_remove(&local_user_view.person, context)
|
|
||||||
.await?;
|
|
||||||
} else {
|
|
||||||
updated_post
|
|
||||||
.send_undo_remove(&local_user_view.person, context)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refetch the post
|
|
||||||
let post_id = data.post_id;
|
|
||||||
let person_id = local_user_view.person.id;
|
|
||||||
let mut post_view = blocking(context.pool(), move |conn| {
|
|
||||||
PostView::read(conn, post_id, Some(person_id))
|
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
send_apub_remove(
|
||||||
|
&local_user_view.person,
|
||||||
|
&community,
|
||||||
|
updated_post.ap_id.into(),
|
||||||
|
data.reason.clone().unwrap_or_else(|| "".to_string()),
|
||||||
|
removed,
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Blank out deleted or removed info
|
send_post_ws_message(
|
||||||
if removed {
|
data.post_id,
|
||||||
post_view.post = post_view.post.blank_out_deleted_or_removed_info();
|
UserOperationCrud::RemovePost,
|
||||||
}
|
|
||||||
|
|
||||||
let res = PostResponse { post_view };
|
|
||||||
|
|
||||||
context.chat_server().do_send(SendPost {
|
|
||||||
op: UserOperationCrud::RemovePost,
|
|
||||||
post: res.clone(),
|
|
||||||
websocket_id,
|
websocket_id,
|
||||||
});
|
Some(local_user_view.person.id),
|
||||||
|
context,
|
||||||
Ok(res)
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,8 @@ use crate::PerformCrud;
|
||||||
use actix_web::web::Data;
|
use actix_web::web::Data;
|
||||||
use lemmy_api_common::{blocking, check_community_ban, get_local_user_view_from_jwt, post::*};
|
use lemmy_api_common::{blocking, check_community_ban, get_local_user_view_from_jwt, post::*};
|
||||||
use lemmy_apub::activities::{post::create_or_update::CreateOrUpdatePost, CreateOrUpdateType};
|
use lemmy_apub::activities::{post::create_or_update::CreateOrUpdatePost, CreateOrUpdateType};
|
||||||
use lemmy_db_queries::{source::post::Post_, Crud, DeleteableOrRemoveable};
|
use lemmy_db_queries::{source::post::Post_, Crud};
|
||||||
use lemmy_db_schema::{naive_now, source::post::*};
|
use lemmy_db_schema::{naive_now, source::post::*};
|
||||||
use lemmy_db_views::post_view::PostView;
|
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
request::fetch_iframely_and_pictrs_data,
|
request::fetch_iframely_and_pictrs_data,
|
||||||
utils::{check_slurs_opt, clean_url_params, is_valid_post_title},
|
utils::{check_slurs_opt, clean_url_params, is_valid_post_title},
|
||||||
|
@ -12,7 +11,7 @@ use lemmy_utils::{
|
||||||
ConnectionId,
|
ConnectionId,
|
||||||
LemmyError,
|
LemmyError,
|
||||||
};
|
};
|
||||||
use lemmy_websocket::{messages::SendPost, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl PerformCrud for EditPost {
|
impl PerformCrud for EditPost {
|
||||||
|
@ -100,25 +99,13 @@ impl PerformCrud for EditPost {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let post_id = data.post_id;
|
send_post_ws_message(
|
||||||
let mut post_view = blocking(context.pool(), move |conn| {
|
data.post_id,
|
||||||
PostView::read(conn, post_id, Some(local_user_view.person.id))
|
UserOperationCrud::EditPost,
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
// Blank out deleted info
|
|
||||||
if post_view.post.deleted || post_view.post.removed {
|
|
||||||
post_view.post = post_view.post.blank_out_deleted_or_removed_info();
|
|
||||||
}
|
|
||||||
|
|
||||||
let res = PostResponse { post_view };
|
|
||||||
|
|
||||||
context.chat_server().do_send(SendPost {
|
|
||||||
op: UserOperationCrud::EditPost,
|
|
||||||
post: res.clone(),
|
|
||||||
websocket_id,
|
websocket_id,
|
||||||
});
|
Some(local_user_view.person.id),
|
||||||
|
context,
|
||||||
Ok(res)
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,9 @@ use lemmy_apub::{
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud};
|
use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud};
|
||||||
use lemmy_db_schema::source::private_message::{PrivateMessage, PrivateMessageForm};
|
use lemmy_db_schema::source::private_message::{PrivateMessage, PrivateMessageForm};
|
||||||
use lemmy_db_views::{local_user_view::LocalUserView, private_message_view::PrivateMessageView};
|
use lemmy_db_views::local_user_view::LocalUserView;
|
||||||
use lemmy_utils::{utils::remove_slurs, ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{utils::remove_slurs, ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl PerformCrud for CreatePrivateMessage {
|
impl PerformCrud for CreatePrivateMessage {
|
||||||
|
@ -78,36 +78,27 @@ impl PerformCrud for CreatePrivateMessage {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let private_message_view = blocking(context.pool(), move |conn| {
|
let res = send_pm_ws_message(
|
||||||
PrivateMessageView::read(conn, inserted_private_message.id)
|
inserted_private_message.id,
|
||||||
})
|
UserOperationCrud::CreatePrivateMessage,
|
||||||
.await??;
|
websocket_id,
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let res = PrivateMessageResponse {
|
// Send email to the local recipient, if one exists
|
||||||
private_message_view,
|
if res.private_message_view.recipient.local {
|
||||||
};
|
|
||||||
|
|
||||||
// Send notifications to the local recipient, if one exists
|
|
||||||
let recipient_id = data.recipient_id;
|
let recipient_id = data.recipient_id;
|
||||||
if let Ok(local_recipient) = blocking(context.pool(), move |conn| {
|
let local_recipient = blocking(context.pool(), move |conn| {
|
||||||
LocalUserView::read_person(conn, recipient_id)
|
LocalUserView::read_person(conn, recipient_id)
|
||||||
})
|
})
|
||||||
.await?
|
.await??;
|
||||||
{
|
|
||||||
send_email_to_user(
|
send_email_to_user(
|
||||||
&local_recipient,
|
&local_recipient,
|
||||||
"Private Message from",
|
"Private Message from",
|
||||||
"Private Message",
|
"Private Message",
|
||||||
&content_slurs_removed,
|
&content_slurs_removed,
|
||||||
);
|
);
|
||||||
|
|
||||||
let local_recipient_id = local_recipient.local_user.id;
|
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
|
||||||
op: UserOperationCrud::CreatePrivateMessage,
|
|
||||||
response: res.clone(),
|
|
||||||
local_recipient_id,
|
|
||||||
websocket_id,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
|
|
|
@ -11,9 +11,8 @@ use lemmy_apub::activities::private_message::{
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud, DeleteableOrRemoveable};
|
use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud, DeleteableOrRemoveable};
|
||||||
use lemmy_db_schema::source::private_message::PrivateMessage;
|
use lemmy_db_schema::source::private_message::PrivateMessage;
|
||||||
use lemmy_db_views::{local_user_view::LocalUserView, private_message_view::PrivateMessageView};
|
|
||||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl PerformCrud for DeletePrivateMessage {
|
impl PerformCrud for DeletePrivateMessage {
|
||||||
|
@ -59,39 +58,7 @@ impl PerformCrud for DeletePrivateMessage {
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let private_message_id = data.private_message_id;
|
let op = UserOperationCrud::DeletePrivateMessage;
|
||||||
let mut private_message_view = blocking(context.pool(), move |conn| {
|
send_pm_ws_message(data.private_message_id, op, websocket_id, context).await
|
||||||
PrivateMessageView::read(conn, private_message_id)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
// Blank out deleted or removed info
|
|
||||||
if deleted {
|
|
||||||
private_message_view.private_message = private_message_view
|
|
||||||
.private_message
|
|
||||||
.blank_out_deleted_or_removed_info();
|
|
||||||
}
|
|
||||||
|
|
||||||
let res = PrivateMessageResponse {
|
|
||||||
private_message_view,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Send notifications to the local recipient, if one exists
|
|
||||||
let recipient_id = orig_private_message.recipient_id;
|
|
||||||
if let Ok(local_recipient) = blocking(context.pool(), move |conn| {
|
|
||||||
LocalUserView::read_person(conn, recipient_id)
|
|
||||||
})
|
|
||||||
.await?
|
|
||||||
{
|
|
||||||
let local_recipient_id = local_recipient.local_user.id;
|
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
|
||||||
op: UserOperationCrud::DeletePrivateMessage,
|
|
||||||
response: res.clone(),
|
|
||||||
local_recipient_id,
|
|
||||||
websocket_id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(res)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,10 @@ use lemmy_apub::activities::{
|
||||||
private_message::create_or_update::CreateOrUpdatePrivateMessage,
|
private_message::create_or_update::CreateOrUpdatePrivateMessage,
|
||||||
CreateOrUpdateType,
|
CreateOrUpdateType,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud, DeleteableOrRemoveable};
|
use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud};
|
||||||
use lemmy_db_schema::source::private_message::PrivateMessage;
|
use lemmy_db_schema::source::private_message::PrivateMessage;
|
||||||
use lemmy_db_views::{local_user_view::LocalUserView, private_message_view::PrivateMessageView};
|
|
||||||
use lemmy_utils::{utils::remove_slurs, ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{utils::remove_slurs, ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl PerformCrud for EditPrivateMessage {
|
impl PerformCrud for EditPrivateMessage {
|
||||||
|
@ -55,39 +54,7 @@ impl PerformCrud for EditPrivateMessage {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let private_message_id = data.private_message_id;
|
let op = UserOperationCrud::EditPrivateMessage;
|
||||||
let mut private_message_view = blocking(context.pool(), move |conn| {
|
send_pm_ws_message(data.private_message_id, op, websocket_id, context).await
|
||||||
PrivateMessageView::read(conn, private_message_id)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
// Blank out deleted or removed info
|
|
||||||
if private_message_view.private_message.deleted {
|
|
||||||
private_message_view.private_message = private_message_view
|
|
||||||
.private_message
|
|
||||||
.blank_out_deleted_or_removed_info();
|
|
||||||
}
|
|
||||||
|
|
||||||
let res = PrivateMessageResponse {
|
|
||||||
private_message_view,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Send notifications to the local recipient, if one exists
|
|
||||||
let recipient_id = orig_private_message.recipient_id;
|
|
||||||
if let Ok(local_recipient) = blocking(context.pool(), move |conn| {
|
|
||||||
LocalUserView::read_person(conn, recipient_id)
|
|
||||||
})
|
|
||||||
.await?
|
|
||||||
{
|
|
||||||
let local_recipient_id = local_recipient.local_user.id;
|
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
|
||||||
op: UserOperationCrud::EditPrivateMessage,
|
|
||||||
response: res.clone(),
|
|
||||||
local_recipient_id,
|
|
||||||
websocket_id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(res)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activities::{
|
activities::{
|
||||||
comment::{collect_non_local_mentions, get_notif_recipients, send_websocket_message},
|
comment::{collect_non_local_mentions, get_notif_recipients},
|
||||||
community::announce::AnnouncableActivities,
|
community::announce::AnnouncableActivities,
|
||||||
extract_community,
|
extract_community,
|
||||||
generate_activity_id,
|
generate_activity_id,
|
||||||
|
@ -24,7 +24,7 @@ use lemmy_apub_lib::{
|
||||||
use lemmy_db_queries::Crud;
|
use lemmy_db_queries::Crud;
|
||||||
use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
|
use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -116,7 +116,11 @@ impl ActivityHandler for CreateOrUpdateComment {
|
||||||
CreateOrUpdateType::Create => UserOperationCrud::CreateComment,
|
CreateOrUpdateType::Create => UserOperationCrud::CreateComment,
|
||||||
CreateOrUpdateType::Update => UserOperationCrud::EditComment,
|
CreateOrUpdateType::Update => UserOperationCrud::EditComment,
|
||||||
};
|
};
|
||||||
send_websocket_message(comment.id, recipients, notif_type, context).await
|
send_comment_ws_message(
|
||||||
|
comment.id, notif_type, None, None, None, recipients, context,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn common(&self) -> &ActivityCommonFields {
|
fn common(&self) -> &ActivityCommonFields {
|
||||||
|
|
|
@ -5,21 +5,19 @@ use activitystreams::{
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use lemmy_api_common::{blocking, comment::CommentResponse, send_local_notifs, WebFingerResponse};
|
use lemmy_api_common::{blocking, send_local_notifs, WebFingerResponse};
|
||||||
use lemmy_db_queries::{Crud, DbPool};
|
use lemmy_db_queries::{Crud, DbPool};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{comment::Comment, community::Community, person::Person, post::Post},
|
source::{comment::Comment, community::Community, person::Person, post::Post},
|
||||||
CommentId,
|
|
||||||
LocalUserId,
|
LocalUserId,
|
||||||
};
|
};
|
||||||
use lemmy_db_views::comment_view::CommentView;
|
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
request::{retry, RecvError},
|
request::{retry, RecvError},
|
||||||
settings::structs::Settings,
|
settings::structs::Settings,
|
||||||
utils::{scrape_text_for_mentions, MentionData},
|
utils::{scrape_text_for_mentions, MentionData},
|
||||||
LemmyError,
|
LemmyError,
|
||||||
};
|
};
|
||||||
use lemmy_websocket::{messages::SendComment, LemmyContext};
|
use lemmy_websocket::LemmyContext;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -45,37 +43,6 @@ async fn get_notif_recipients(
|
||||||
send_local_notifs(mentions, comment.clone(), actor, post, context.pool(), true).await
|
send_local_notifs(mentions, comment.clone(), actor, post, context.pool(), true).await
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: in many call sites we are setting an empty vec for recipient_ids, we should get the actual
|
|
||||||
// recipient actors from somewhere
|
|
||||||
pub(crate) async fn send_websocket_message<
|
|
||||||
OP: ToString + Send + lemmy_websocket::OperationType + 'static,
|
|
||||||
>(
|
|
||||||
comment_id: CommentId,
|
|
||||||
recipient_ids: Vec<LocalUserId>,
|
|
||||||
op: OP,
|
|
||||||
context: &LemmyContext,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
// Refetch the view
|
|
||||||
let comment_view = blocking(context.pool(), move |conn| {
|
|
||||||
CommentView::read(conn, comment_id, None)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
let res = CommentResponse {
|
|
||||||
comment_view,
|
|
||||||
recipient_ids,
|
|
||||||
form_id: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
context.chat_server().do_send(SendComment {
|
|
||||||
op,
|
|
||||||
comment: res,
|
|
||||||
websocket_id: None,
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct MentionsAndAddresses {
|
pub struct MentionsAndAddresses {
|
||||||
pub ccs: Vec<Url>,
|
pub ccs: Vec<Url>,
|
||||||
pub inboxes: Vec<Url>,
|
pub inboxes: Vec<Url>,
|
||||||
|
|
|
@ -7,16 +7,10 @@ use crate::{
|
||||||
list_community_follower_inboxes,
|
list_community_follower_inboxes,
|
||||||
undo_block_user::UndoBlockUserFromCommunity,
|
undo_block_user::UndoBlockUserFromCommunity,
|
||||||
},
|
},
|
||||||
deletion::{
|
deletion::{delete::Delete, undo_delete::UndoDelete},
|
||||||
delete::DeletePostCommentOrCommunity,
|
|
||||||
undo_delete::UndoDeletePostCommentOrCommunity,
|
|
||||||
},
|
|
||||||
generate_activity_id,
|
generate_activity_id,
|
||||||
post::create_or_update::CreateOrUpdatePost,
|
post::create_or_update::CreateOrUpdatePost,
|
||||||
removal::{
|
removal::{remove::RemoveMod, undo_remove::UndoRemovePostCommentOrCommunity},
|
||||||
remove::RemovePostCommentCommunityOrMod,
|
|
||||||
undo_remove::UndoRemovePostCommentOrCommunity,
|
|
||||||
},
|
|
||||||
verify_activity,
|
verify_activity,
|
||||||
verify_community,
|
verify_community,
|
||||||
voting::{undo_vote::UndoVote, vote::Vote},
|
voting::{undo_vote::UndoVote, vote::Vote},
|
||||||
|
@ -43,13 +37,13 @@ pub enum AnnouncableActivities {
|
||||||
CreateOrUpdatePost(Box<CreateOrUpdatePost>),
|
CreateOrUpdatePost(Box<CreateOrUpdatePost>),
|
||||||
Vote(Vote),
|
Vote(Vote),
|
||||||
UndoVote(UndoVote),
|
UndoVote(UndoVote),
|
||||||
DeletePostCommentOrCommunity(DeletePostCommentOrCommunity),
|
Delete(Delete),
|
||||||
UndoDeletePostCommentOrCommunity(UndoDeletePostCommentOrCommunity),
|
UndoDelete(UndoDelete),
|
||||||
RemovePostCommentCommunityOrMod(RemovePostCommentCommunityOrMod),
|
|
||||||
UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
|
UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
|
||||||
BlockUserFromCommunity(BlockUserFromCommunity),
|
BlockUserFromCommunity(BlockUserFromCommunity),
|
||||||
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
|
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
|
||||||
AddMod(AddMod),
|
AddMod(AddMod),
|
||||||
|
RemoveMod(RemoveMod),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
use crate::{check_is_apub_id_valid, CommunityType};
|
use crate::{check_is_apub_id_valid, CommunityType};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use lemmy_api_common::{blocking, community::CommunityResponse};
|
use lemmy_db_schema::source::community::Community;
|
||||||
use lemmy_db_schema::{source::community::Community, CommunityId};
|
|
||||||
use lemmy_db_views_actor::community_view::CommunityView;
|
|
||||||
use lemmy_utils::{settings::structs::Settings, LemmyError};
|
use lemmy_utils::{settings::structs::Settings, LemmyError};
|
||||||
use lemmy_websocket::{messages::SendCommunityRoomMessage, LemmyContext};
|
use lemmy_websocket::LemmyContext;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub mod add_mod;
|
pub mod add_mod;
|
||||||
|
@ -13,30 +11,6 @@ pub mod block_user;
|
||||||
pub mod undo_block_user;
|
pub mod undo_block_user;
|
||||||
pub mod update;
|
pub mod update;
|
||||||
|
|
||||||
pub(crate) async fn send_websocket_message<
|
|
||||||
OP: ToString + Send + lemmy_websocket::OperationType + 'static,
|
|
||||||
>(
|
|
||||||
community_id: CommunityId,
|
|
||||||
op: OP,
|
|
||||||
context: &LemmyContext,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
let community_view = blocking(context.pool(), move |conn| {
|
|
||||||
CommunityView::read(conn, community_id, None)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
let res = CommunityResponse { community_view };
|
|
||||||
|
|
||||||
context.chat_server().do_send(SendCommunityRoomMessage {
|
|
||||||
op,
|
|
||||||
response: res,
|
|
||||||
community_id,
|
|
||||||
websocket_id: None,
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn list_community_follower_inboxes(
|
async fn list_community_follower_inboxes(
|
||||||
community: &Community,
|
community: &Community,
|
||||||
additional_inboxes: Vec<Url>,
|
additional_inboxes: Vec<Url>,
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activities::{
|
activities::{verify_activity, verify_mod_action, verify_person_in_community},
|
||||||
community::send_websocket_message,
|
|
||||||
verify_activity,
|
|
||||||
verify_mod_action,
|
|
||||||
verify_person_in_community,
|
|
||||||
},
|
|
||||||
objects::community::Group,
|
objects::community::Group,
|
||||||
};
|
};
|
||||||
use activitystreams::activity::kind::UpdateType;
|
use activitystreams::activity::kind::UpdateType;
|
||||||
|
@ -13,7 +8,7 @@ use lemmy_apub_lib::{values::PublicUrl, ActivityCommonFields, ActivityHandler};
|
||||||
use lemmy_db_queries::{ApubObject, Crud};
|
use lemmy_db_queries::{ApubObject, Crud};
|
||||||
use lemmy_db_schema::source::community::{Community, CommunityForm};
|
use lemmy_db_schema::source::community::{Community, CommunityForm};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
/// This activity is received from a remote community mod, and updates the description or other
|
/// This activity is received from a remote community mod, and updates the description or other
|
||||||
|
@ -71,12 +66,15 @@ impl ActivityHandler for UpdateCommunity {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
send_websocket_message(
|
send_community_ws_message(
|
||||||
updated_community.id,
|
updated_community.id,
|
||||||
UserOperationCrud::EditCommunity,
|
UserOperationCrud::EditCommunity,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
.await
|
.await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn common(&self) -> &ActivityCommonFields {
|
fn common(&self) -> &ActivityCommonFields {
|
||||||
|
|
|
@ -1,31 +1,48 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activities::{
|
activities::{
|
||||||
comment::send_websocket_message as send_comment_message,
|
community::announce::AnnouncableActivities,
|
||||||
community::send_websocket_message as send_community_message,
|
deletion::{
|
||||||
post::send_websocket_message as send_post_message,
|
receive_delete_action,
|
||||||
|
verify_delete_activity,
|
||||||
|
DeletableObjects,
|
||||||
|
WebsocketMessages,
|
||||||
|
},
|
||||||
|
generate_activity_id,
|
||||||
verify_activity,
|
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,
|
|
||||||
},
|
},
|
||||||
|
activity_queue::send_to_community_new,
|
||||||
|
extensions::context::lemmy_context,
|
||||||
|
fetcher::person::get_or_fetch_and_upsert_person,
|
||||||
ActorType,
|
ActorType,
|
||||||
CommunityType,
|
|
||||||
PostOrComment,
|
|
||||||
};
|
};
|
||||||
use activitystreams::activity::kind::DeleteType;
|
use activitystreams::activity::kind::DeleteType;
|
||||||
|
use anyhow::anyhow;
|
||||||
use lemmy_api_common::blocking;
|
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::{
|
use lemmy_db_queries::{
|
||||||
source::{comment::Comment_, community::Community_, post::Post_},
|
source::{comment::Comment_, community::Community_, post::Post_},
|
||||||
Crud,
|
Crud,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
|
use lemmy_db_schema::source::{
|
||||||
|
comment::Comment,
|
||||||
|
community::Community,
|
||||||
|
moderator::{
|
||||||
|
ModRemoveComment,
|
||||||
|
ModRemoveCommentForm,
|
||||||
|
ModRemoveCommunity,
|
||||||
|
ModRemoveCommunityForm,
|
||||||
|
ModRemovePost,
|
||||||
|
ModRemovePostForm,
|
||||||
|
},
|
||||||
|
person::Person,
|
||||||
|
post::Post,
|
||||||
|
};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{
|
||||||
|
send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message},
|
||||||
|
LemmyContext,
|
||||||
|
UserOperationCrud,
|
||||||
|
};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
/// This is very confusing, because there are four distinct cases to handle:
|
/// This is very confusing, because there are four distinct cases to handle:
|
||||||
|
@ -38,38 +55,36 @@ use url::Url;
|
||||||
/// wrapping it in an announce just like other activities, instead of having the community send it.
|
/// wrapping it in an announce just like other activities, instead of having the community send it.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct DeletePostCommentOrCommunity {
|
pub struct Delete {
|
||||||
to: PublicUrl,
|
pub(in crate::activities::deletion) to: PublicUrl,
|
||||||
pub(in crate::activities::deletion) object: Url,
|
pub(in crate::activities::deletion) object: Url,
|
||||||
cc: [Url; 1],
|
pub(in crate::activities::deletion) cc: [Url; 1],
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: DeleteType,
|
pub(in crate::activities::deletion) kind: DeleteType,
|
||||||
|
/// If summary is present, this is a mod action (Remove in Lemmy terms). Otherwise, its a user
|
||||||
|
/// deleting their own content.
|
||||||
|
pub(in crate::activities::deletion) summary: Option<String>,
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
common: ActivityCommonFields,
|
pub(in crate::activities::deletion) common: ActivityCommonFields,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ActivityHandler for DeletePostCommentOrCommunity {
|
impl ActivityHandler for Delete {
|
||||||
async fn verify(
|
async fn verify(
|
||||||
&self,
|
&self,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
verify_activity(self.common())?;
|
verify_activity(self.common())?;
|
||||||
let object_community =
|
verify_delete_activity(
|
||||||
get_or_fetch_and_upsert_community(&self.object, context, request_counter).await;
|
&self.object,
|
||||||
// deleting a community (set counter 0 to only fetch from local db)
|
&self.cc[0],
|
||||||
if object_community.is_ok() {
|
&self.common,
|
||||||
verify_mod_action(&self.common.actor, self.object.clone(), context).await?;
|
self.summary.is_some(),
|
||||||
}
|
context,
|
||||||
// deleting a post or comment
|
request_counter,
|
||||||
else {
|
)
|
||||||
verify_person_in_community(&self.common().actor, &self.cc[0], context, request_counter)
|
|
||||||
.await?;
|
.await?;
|
||||||
let object_creator =
|
|
||||||
get_post_or_comment_actor_id(&self.object, context, request_counter).await?;
|
|
||||||
verify_urls_match(&self.common.actor, &object_creator)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,82 +93,140 @@ impl ActivityHandler for DeletePostCommentOrCommunity {
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let object_community =
|
if let Some(reason) = self.summary {
|
||||||
get_or_fetch_and_upsert_community(&self.object, context, request_counter).await;
|
// We set reason to empty string if it doesn't exist, to distinguish between delete and
|
||||||
// deleting a community
|
// remove. Here we change it back to option, so we don't write it to db.
|
||||||
if let Ok(community) = object_community {
|
let reason = if reason.is_empty() {
|
||||||
if community.local {
|
None
|
||||||
// repeat these checks just to be sure
|
} else {
|
||||||
verify_person_in_community(&self.common().actor, &self.cc[0], context, request_counter)
|
Some(reason)
|
||||||
.await?;
|
};
|
||||||
verify_mod_action(&self.common.actor, self.object.clone(), context).await?;
|
receive_remove_action(
|
||||||
let mod_ =
|
&self.common.actor,
|
||||||
get_or_fetch_and_upsert_person(&self.common.actor, context, request_counter).await?;
|
&self.object,
|
||||||
community.send_delete(mod_, context).await?;
|
reason,
|
||||||
}
|
|
||||||
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,
|
context,
|
||||||
|
request_counter,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
} else {
|
||||||
// deleting a post or comment
|
receive_delete_action(
|
||||||
else {
|
&self.object,
|
||||||
match get_or_fetch_and_insert_post_or_comment(&self.object, context, request_counter).await? {
|
&self.common.actor,
|
||||||
PostOrComment::Post(post) => {
|
WebsocketMessages {
|
||||||
let deleted_post = blocking(context.pool(), move |conn| {
|
community: UserOperationCrud::DeleteCommunity,
|
||||||
Post::update_deleted(conn, post.id, true)
|
post: UserOperationCrud::DeletePost,
|
||||||
})
|
comment: UserOperationCrud::DeleteComment,
|
||||||
.await??;
|
},
|
||||||
send_post_message(deleted_post.id, UserOperationCrud::EditPost, context).await
|
true,
|
||||||
}
|
|
||||||
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,
|
context,
|
||||||
|
request_counter,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn common(&self) -> &ActivityCommonFields {
|
fn common(&self) -> &ActivityCommonFields {
|
||||||
&self.common
|
&self.common
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_post_or_comment_actor_id(
|
impl Delete {
|
||||||
|
pub(in crate::activities::deletion) async fn send(
|
||||||
|
actor: &Person,
|
||||||
|
community: &Community,
|
||||||
|
object_id: Url,
|
||||||
|
summary: Option<String>,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
let id = generate_activity_id(DeleteType::Delete)?;
|
||||||
|
let delete = Delete {
|
||||||
|
to: PublicUrl::Public,
|
||||||
|
object: object_id,
|
||||||
|
cc: [community.actor_id()],
|
||||||
|
kind: DeleteType::Delete,
|
||||||
|
summary,
|
||||||
|
common: ActivityCommonFields {
|
||||||
|
context: lemmy_context(),
|
||||||
|
id: id.clone(),
|
||||||
|
actor: actor.actor_id(),
|
||||||
|
unparsed: Default::default(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let activity = AnnouncableActivities::Delete(delete);
|
||||||
|
send_to_community_new(activity, &id, actor, community, vec![], context).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(in crate::activities) async fn receive_remove_action(
|
||||||
|
actor: &Url,
|
||||||
object: &Url,
|
object: &Url,
|
||||||
|
reason: Option<String>,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<Url, LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let actor_id =
|
let actor = get_or_fetch_and_upsert_person(actor, context, request_counter).await?;
|
||||||
match get_or_fetch_and_insert_post_or_comment(object, context, request_counter).await? {
|
use UserOperationCrud::*;
|
||||||
PostOrComment::Post(post) => {
|
match DeletableObjects::read_from_db(object, context).await? {
|
||||||
let creator_id = post.creator_id;
|
DeletableObjects::Community(community) => {
|
||||||
blocking(context.pool(), move |conn| Person::read(conn, creator_id))
|
if community.local {
|
||||||
.await??
|
return Err(anyhow!("Only local admin can remove community").into());
|
||||||
.actor_id()
|
|
||||||
}
|
|
||||||
PostOrComment::Comment(comment) => {
|
|
||||||
let creator_id = comment.creator_id;
|
|
||||||
blocking(context.pool(), move |conn| Person::read(conn, creator_id))
|
|
||||||
.await??
|
|
||||||
.actor_id()
|
|
||||||
}
|
}
|
||||||
|
let form = ModRemoveCommunityForm {
|
||||||
|
mod_person_id: actor.id,
|
||||||
|
community_id: community.id,
|
||||||
|
removed: Some(true),
|
||||||
|
reason,
|
||||||
|
expires: None,
|
||||||
};
|
};
|
||||||
Ok(actor_id)
|
blocking(context.pool(), move |conn| {
|
||||||
|
ModRemoveCommunity::create(conn, &form)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
let deleted_community = blocking(context.pool(), move |conn| {
|
||||||
|
Community::update_removed(conn, community.id, true)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
|
||||||
|
send_community_ws_message(deleted_community.id, RemoveCommunity, None, None, context).await?;
|
||||||
|
}
|
||||||
|
DeletableObjects::Post(post) => {
|
||||||
|
let form = ModRemovePostForm {
|
||||||
|
mod_person_id: actor.id,
|
||||||
|
post_id: post.id,
|
||||||
|
removed: Some(true),
|
||||||
|
reason,
|
||||||
|
};
|
||||||
|
blocking(context.pool(), move |conn| {
|
||||||
|
ModRemovePost::create(conn, &form)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
let removed_post = blocking(context.pool(), move |conn| {
|
||||||
|
Post::update_removed(conn, post.id, true)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
|
||||||
|
send_post_ws_message(removed_post.id, RemovePost, None, None, context).await?;
|
||||||
|
}
|
||||||
|
DeletableObjects::Comment(comment) => {
|
||||||
|
let form = ModRemoveCommentForm {
|
||||||
|
mod_person_id: actor.id,
|
||||||
|
comment_id: comment.id,
|
||||||
|
removed: Some(true),
|
||||||
|
reason,
|
||||||
|
};
|
||||||
|
blocking(context.pool(), move |conn| {
|
||||||
|
ModRemoveComment::create(conn, &form)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
let removed_comment = blocking(context.pool(), move |conn| {
|
||||||
|
Comment::update_removed(conn, comment.id, true)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
|
||||||
|
send_comment_ws_message_simple(removed_comment.id, RemoveComment, context).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,209 @@
|
||||||
|
use crate::{
|
||||||
|
activities::{
|
||||||
|
deletion::{delete::Delete, undo_delete::UndoDelete},
|
||||||
|
verify_mod_action,
|
||||||
|
verify_person_in_community,
|
||||||
|
},
|
||||||
|
fetcher::person::get_or_fetch_and_upsert_person,
|
||||||
|
ActorType,
|
||||||
|
};
|
||||||
|
use lemmy_api_common::blocking;
|
||||||
|
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields};
|
||||||
|
use lemmy_db_queries::{
|
||||||
|
source::{comment::Comment_, community::Community_, post::Post_},
|
||||||
|
ApubObject,
|
||||||
|
};
|
||||||
|
use lemmy_db_schema::{
|
||||||
|
source::{comment::Comment, community::Community, person::Person, post::Post},
|
||||||
|
DbUrl,
|
||||||
|
};
|
||||||
|
use lemmy_utils::LemmyError;
|
||||||
|
use lemmy_websocket::{
|
||||||
|
send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message},
|
||||||
|
LemmyContext,
|
||||||
|
UserOperationCrud,
|
||||||
|
};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
pub mod delete;
|
pub mod delete;
|
||||||
pub mod undo_delete;
|
pub mod undo_delete;
|
||||||
|
|
||||||
|
pub async fn send_apub_delete(
|
||||||
|
actor: &Person,
|
||||||
|
community: &Community,
|
||||||
|
object_id: Url,
|
||||||
|
deleted: bool,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
if deleted {
|
||||||
|
Delete::send(actor, community, object_id, None, context).await
|
||||||
|
} else {
|
||||||
|
UndoDelete::send(actor, community, object_id, None, context).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove reason is actually optional in lemmy. we set an empty string in that case, but its
|
||||||
|
// ugly
|
||||||
|
pub async fn send_apub_remove(
|
||||||
|
actor: &Person,
|
||||||
|
community: &Community,
|
||||||
|
object_id: Url,
|
||||||
|
reason: String,
|
||||||
|
removed: bool,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
if removed {
|
||||||
|
Delete::send(actor, community, object_id, Some(reason), context).await
|
||||||
|
} else {
|
||||||
|
UndoDelete::send(actor, community, object_id, Some(reason), context).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) async fn verify_delete_activity(
|
||||||
|
object: &Url,
|
||||||
|
cc: &Url,
|
||||||
|
common: &ActivityCommonFields,
|
||||||
|
is_mod_action: bool,
|
||||||
|
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?;
|
||||||
|
}
|
||||||
|
// community deletion is always a mod (or admin) action
|
||||||
|
verify_mod_action(&common.actor, c.actor_id(), context).await?;
|
||||||
|
}
|
||||||
|
DeletableObjects::Post(p) => {
|
||||||
|
verify_delete_activity_post_or_comment(
|
||||||
|
cc,
|
||||||
|
common,
|
||||||
|
&p.ap_id.into(),
|
||||||
|
is_mod_action,
|
||||||
|
context,
|
||||||
|
request_counter,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
DeletableObjects::Comment(c) => {
|
||||||
|
verify_delete_activity_post_or_comment(
|
||||||
|
cc,
|
||||||
|
common,
|
||||||
|
&c.ap_id.into(),
|
||||||
|
is_mod_action,
|
||||||
|
context,
|
||||||
|
request_counter,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn verify_delete_activity_post_or_comment(
|
||||||
|
cc: &Url,
|
||||||
|
common: &ActivityCommonFields,
|
||||||
|
object_id: &Url,
|
||||||
|
is_mod_action: bool,
|
||||||
|
context: &LemmyContext,
|
||||||
|
request_counter: &mut i32,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
verify_person_in_community(&common.actor, cc, context, request_counter).await?;
|
||||||
|
if is_mod_action {
|
||||||
|
verify_mod_action(&common.actor, cc.clone(), context).await?;
|
||||||
|
} else {
|
||||||
|
// domain of post ap_id and post.creator ap_id are identical, so we just check the former
|
||||||
|
verify_domains_match(&common.actor, object_id)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WebsocketMessages {
|
||||||
|
community: UserOperationCrud,
|
||||||
|
post: UserOperationCrud,
|
||||||
|
comment: UserOperationCrud,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write deletion or restoring of an object to the database, and send websocket message.
|
||||||
|
/// TODO: we should do something similar for receive_remove_action(), but its much more complicated
|
||||||
|
/// because of the mod log
|
||||||
|
async fn receive_delete_action(
|
||||||
|
object: &Url,
|
||||||
|
actor: &Url,
|
||||||
|
ws_messages: WebsocketMessages,
|
||||||
|
deleted: bool,
|
||||||
|
context: &LemmyContext,
|
||||||
|
request_counter: &mut i32,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
match DeletableObjects::read_from_db(object, context).await? {
|
||||||
|
DeletableObjects::Community(community) => {
|
||||||
|
if community.local {
|
||||||
|
let mod_ = get_or_fetch_and_upsert_person(actor, context, request_counter).await?;
|
||||||
|
let object = community.actor_id();
|
||||||
|
send_apub_delete(&mod_, &community.clone(), object, true, context).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let community = blocking(context.pool(), move |conn| {
|
||||||
|
Community::update_deleted(conn, community.id, deleted)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
send_community_ws_message(community.id, ws_messages.community, None, None, context).await?;
|
||||||
|
}
|
||||||
|
DeletableObjects::Post(post) => {
|
||||||
|
let deleted_post = blocking(context.pool(), move |conn| {
|
||||||
|
Post::update_deleted(conn, post.id, deleted)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
send_post_ws_message(deleted_post.id, ws_messages.post, None, None, context).await?;
|
||||||
|
}
|
||||||
|
DeletableObjects::Comment(comment) => {
|
||||||
|
let deleted_comment = blocking(context.pool(), move |conn| {
|
||||||
|
Comment::update_deleted(conn, comment.id, deleted)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
send_comment_ws_message_simple(deleted_comment.id, ws_messages.comment, context).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
@ -1,35 +1,39 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activities::{
|
activities::{
|
||||||
comment::send_websocket_message as send_comment_message,
|
community::announce::AnnouncableActivities,
|
||||||
community::send_websocket_message as send_community_message,
|
deletion::{
|
||||||
deletion::delete::DeletePostCommentOrCommunity,
|
delete::Delete,
|
||||||
post::send_websocket_message as send_post_message,
|
receive_delete_action,
|
||||||
|
verify_delete_activity,
|
||||||
|
DeletableObjects,
|
||||||
|
WebsocketMessages,
|
||||||
|
},
|
||||||
|
generate_activity_id,
|
||||||
verify_activity,
|
verify_activity,
|
||||||
verify_mod_action,
|
|
||||||
verify_person_in_community,
|
|
||||||
},
|
},
|
||||||
fetcher::{
|
activity_queue::send_to_community_new,
|
||||||
community::get_or_fetch_and_upsert_community,
|
extensions::context::lemmy_context,
|
||||||
objects::get_or_fetch_and_insert_post_or_comment,
|
ActorType,
|
||||||
person::get_or_fetch_and_upsert_person,
|
|
||||||
},
|
|
||||||
CommunityType,
|
|
||||||
PostOrComment,
|
|
||||||
};
|
};
|
||||||
use activitystreams::activity::kind::UndoType;
|
use activitystreams::activity::kind::{DeleteType, UndoType};
|
||||||
|
use anyhow::anyhow;
|
||||||
use lemmy_api_common::blocking;
|
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_queries::source::{comment::Comment_, community::Community_, post::Post_};
|
||||||
use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post};
|
use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{
|
||||||
|
send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message},
|
||||||
|
LemmyContext,
|
||||||
|
UserOperationCrud,
|
||||||
|
};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct UndoDeletePostCommentOrCommunity {
|
pub struct UndoDelete {
|
||||||
to: PublicUrl,
|
to: PublicUrl,
|
||||||
object: DeletePostCommentOrCommunity,
|
object: Delete,
|
||||||
cc: [Url; 1],
|
cc: [Url; 1],
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: UndoType,
|
kind: UndoType,
|
||||||
|
@ -38,7 +42,7 @@ pub struct UndoDeletePostCommentOrCommunity {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ActivityHandler for UndoDeletePostCommentOrCommunity {
|
impl ActivityHandler for UndoDelete {
|
||||||
async fn verify(
|
async fn verify(
|
||||||
&self,
|
&self,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
|
@ -46,18 +50,15 @@ impl ActivityHandler for UndoDeletePostCommentOrCommunity {
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
verify_activity(self.common())?;
|
verify_activity(self.common())?;
|
||||||
self.object.verify(context, request_counter).await?;
|
self.object.verify(context, request_counter).await?;
|
||||||
let object_community =
|
verify_delete_activity(
|
||||||
get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await;
|
&self.object.object,
|
||||||
// restoring a community
|
&self.cc[0],
|
||||||
if object_community.is_ok() {
|
&self.common,
|
||||||
verify_mod_action(&self.common.actor, self.object.object.clone(), context).await?;
|
self.object.summary.is_some(),
|
||||||
}
|
context,
|
||||||
// restoring a post or comment
|
request_counter,
|
||||||
else {
|
)
|
||||||
verify_person_in_community(&self.common().actor, &self.cc[0], context, request_counter)
|
|
||||||
.await?;
|
.await?;
|
||||||
verify_urls_match(&self.common.actor, &self.object.common().actor)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,61 +67,101 @@ impl ActivityHandler for UndoDeletePostCommentOrCommunity {
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let object_community =
|
if self.object.summary.is_some() {
|
||||||
get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await;
|
UndoDelete::receive_undo_remove_action(&self.object.object, context).await
|
||||||
// restoring a community
|
} else {
|
||||||
if let Ok(community) = object_community {
|
receive_delete_action(
|
||||||
if community.local {
|
&self.object.object,
|
||||||
// repeat these checks just to be sure
|
&self.common.actor,
|
||||||
verify_person_in_community(&self.common().actor, &self.cc[0], context, request_counter)
|
WebsocketMessages {
|
||||||
.await?;
|
community: UserOperationCrud::EditCommunity,
|
||||||
verify_mod_action(&self.common.actor, self.object.object.clone(), context).await?;
|
post: UserOperationCrud::EditPost,
|
||||||
let mod_ =
|
comment: UserOperationCrud::EditComment,
|
||||||
get_or_fetch_and_upsert_person(&self.common.actor, context, request_counter).await?;
|
},
|
||||||
community.send_undo_delete(mod_, context).await?;
|
false,
|
||||||
}
|
|
||||||
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,
|
context,
|
||||||
|
request_counter,
|
||||||
)
|
)
|
||||||
.await
|
.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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn common(&self) -> &ActivityCommonFields {
|
fn common(&self) -> &ActivityCommonFields {
|
||||||
&self.common
|
&self.common
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl UndoDelete {
|
||||||
|
pub(in crate::activities::deletion) async fn send(
|
||||||
|
actor: &Person,
|
||||||
|
community: &Community,
|
||||||
|
object_id: Url,
|
||||||
|
summary: Option<String>,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
let delete = Delete {
|
||||||
|
to: PublicUrl::Public,
|
||||||
|
object: object_id,
|
||||||
|
cc: [community.actor_id()],
|
||||||
|
kind: DeleteType::Delete,
|
||||||
|
summary,
|
||||||
|
common: ActivityCommonFields {
|
||||||
|
context: lemmy_context(),
|
||||||
|
id: generate_activity_id(DeleteType::Delete)?,
|
||||||
|
actor: actor.actor_id(),
|
||||||
|
unparsed: Default::default(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let id = generate_activity_id(UndoType::Undo)?;
|
||||||
|
let undo = UndoDelete {
|
||||||
|
to: PublicUrl::Public,
|
||||||
|
object: delete,
|
||||||
|
cc: [community.actor_id()],
|
||||||
|
kind: UndoType::Undo,
|
||||||
|
common: ActivityCommonFields {
|
||||||
|
context: lemmy_context(),
|
||||||
|
id: id.clone(),
|
||||||
|
actor: actor.actor_id(),
|
||||||
|
unparsed: Default::default(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let activity = AnnouncableActivities::UndoDelete(undo);
|
||||||
|
send_to_community_new(activity, &id, actor, community, vec![], context).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(in crate::activities) async fn receive_undo_remove_action(
|
||||||
|
object: &Url,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
use UserOperationCrud::*;
|
||||||
|
match DeletableObjects::read_from_db(object, context).await? {
|
||||||
|
DeletableObjects::Community(community) => {
|
||||||
|
if community.local {
|
||||||
|
return Err(anyhow!("Only local admin can restore community").into());
|
||||||
|
}
|
||||||
|
let deleted_community = blocking(context.pool(), move |conn| {
|
||||||
|
Community::update_removed(conn, community.id, false)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
send_community_ws_message(deleted_community.id, EditCommunity, None, None, context).await?;
|
||||||
|
}
|
||||||
|
DeletableObjects::Post(post) => {
|
||||||
|
let removed_post = blocking(context.pool(), move |conn| {
|
||||||
|
Post::update_removed(conn, post.id, false)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
send_post_ws_message(removed_post.id, EditPost, None, None, context).await?;
|
||||||
|
}
|
||||||
|
DeletableObjects::Comment(comment) => {
|
||||||
|
let removed_comment = blocking(context.pool(), move |conn| {
|
||||||
|
Comment::update_removed(conn, comment.id, false)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
send_comment_ws_message_simple(removed_comment.id, EditComment, context).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ use crate::{
|
||||||
community::announce::AnnouncableActivities,
|
community::announce::AnnouncableActivities,
|
||||||
extract_community,
|
extract_community,
|
||||||
generate_activity_id,
|
generate_activity_id,
|
||||||
post::send_websocket_message,
|
|
||||||
verify_activity,
|
verify_activity,
|
||||||
verify_mod_action,
|
verify_mod_action,
|
||||||
verify_person_in_community,
|
verify_person_in_community,
|
||||||
|
@ -27,7 +26,7 @@ use lemmy_apub_lib::{
|
||||||
use lemmy_db_queries::Crud;
|
use lemmy_db_queries::Crud;
|
||||||
use lemmy_db_schema::source::{community::Community, person::Person, post::Post};
|
use lemmy_db_schema::source::{community::Community, person::Person, post::Post};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
|
@ -126,7 +125,8 @@ impl ActivityHandler for CreateOrUpdatePost {
|
||||||
CreateOrUpdateType::Create => UserOperationCrud::CreatePost,
|
CreateOrUpdateType::Create => UserOperationCrud::CreatePost,
|
||||||
CreateOrUpdateType::Update => UserOperationCrud::EditPost,
|
CreateOrUpdateType::Update => UserOperationCrud::EditPost,
|
||||||
};
|
};
|
||||||
send_websocket_message(post.id, notif_type, context).await
|
send_post_ws_message(post.id, notif_type, None, None, context).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn common(&self) -> &ActivityCommonFields {
|
fn common(&self) -> &ActivityCommonFields {
|
||||||
|
|
|
@ -1,30 +1 @@
|
||||||
use lemmy_api_common::{blocking, post::PostResponse};
|
|
||||||
use lemmy_db_schema::PostId;
|
|
||||||
use lemmy_db_views::post_view::PostView;
|
|
||||||
use lemmy_utils::LemmyError;
|
|
||||||
use lemmy_websocket::{messages::SendPost, LemmyContext};
|
|
||||||
|
|
||||||
pub mod create_or_update;
|
pub mod create_or_update;
|
||||||
|
|
||||||
pub(crate) async fn send_websocket_message<
|
|
||||||
OP: ToString + Send + lemmy_websocket::OperationType + 'static,
|
|
||||||
>(
|
|
||||||
post_id: PostId,
|
|
||||||
op: OP,
|
|
||||||
context: &LemmyContext,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
let post_view = blocking(context.pool(), move |conn| {
|
|
||||||
PostView::read(conn, post_id, None)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
let res = PostResponse { post_view };
|
|
||||||
|
|
||||||
context.chat_server().do_send(SendPost {
|
|
||||||
op,
|
|
||||||
post: res,
|
|
||||||
websocket_id: None,
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,11 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activities::{
|
activities::{generate_activity_id, verify_activity, verify_person, CreateOrUpdateType},
|
||||||
generate_activity_id,
|
|
||||||
private_message::send_websocket_message,
|
|
||||||
verify_activity,
|
|
||||||
verify_person,
|
|
||||||
CreateOrUpdateType,
|
|
||||||
},
|
|
||||||
activity_queue::send_activity_new,
|
activity_queue::send_activity_new,
|
||||||
extensions::context::lemmy_context,
|
extensions::context::lemmy_context,
|
||||||
objects::{private_message::Note, FromApub, ToApub},
|
objects::{private_message::Note, FromApub, ToApub},
|
||||||
|
@ -16,7 +10,7 @@ use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandler
|
||||||
use lemmy_db_queries::Crud;
|
use lemmy_db_queries::Crud;
|
||||||
use lemmy_db_schema::source::{person::Person, private_message::PrivateMessage};
|
use lemmy_db_schema::source::{person::Person, private_message::PrivateMessage};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
|
@ -83,7 +77,7 @@ impl ActivityHandler for CreateOrUpdatePrivateMessage {
|
||||||
CreateOrUpdateType::Create => UserOperationCrud::CreatePrivateMessage,
|
CreateOrUpdateType::Create => UserOperationCrud::CreatePrivateMessage,
|
||||||
CreateOrUpdateType::Update => UserOperationCrud::EditPrivateMessage,
|
CreateOrUpdateType::Update => UserOperationCrud::EditPrivateMessage,
|
||||||
};
|
};
|
||||||
send_websocket_message(private_message.id, notif_type, context).await?;
|
send_pm_ws_message(private_message.id, notif_type, None, context).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activities::{
|
activities::{generate_activity_id, verify_activity, verify_person},
|
||||||
generate_activity_id,
|
|
||||||
private_message::send_websocket_message,
|
|
||||||
verify_activity,
|
|
||||||
verify_person,
|
|
||||||
},
|
|
||||||
activity_queue::send_activity_new,
|
activity_queue::send_activity_new,
|
||||||
extensions::context::lemmy_context,
|
extensions::context::lemmy_context,
|
||||||
ActorType,
|
ActorType,
|
||||||
|
@ -15,7 +10,7 @@ use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandler
|
||||||
use lemmy_db_queries::{source::private_message::PrivateMessage_, ApubObject, Crud};
|
use lemmy_db_queries::{source::private_message::PrivateMessage_, ApubObject, Crud};
|
||||||
use lemmy_db_schema::source::{person::Person, private_message::PrivateMessage};
|
use lemmy_db_schema::source::{person::Person, private_message::PrivateMessage};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
|
@ -84,9 +79,10 @@ impl ActivityHandler for DeletePrivateMessage {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
send_websocket_message(
|
send_pm_ws_message(
|
||||||
deleted_private_message.id,
|
deleted_private_message.id,
|
||||||
UserOperationCrud::DeletePrivateMessage,
|
UserOperationCrud::DeletePrivateMessage,
|
||||||
|
None,
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
|
@ -1,41 +1,3 @@
|
||||||
use lemmy_api_common::{blocking, person::PrivateMessageResponse};
|
|
||||||
use lemmy_db_schema::PrivateMessageId;
|
|
||||||
use lemmy_db_views::{local_user_view::LocalUserView, private_message_view::PrivateMessageView};
|
|
||||||
use lemmy_utils::LemmyError;
|
|
||||||
use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperationCrud};
|
|
||||||
|
|
||||||
pub mod create_or_update;
|
pub mod create_or_update;
|
||||||
pub mod delete;
|
pub mod delete;
|
||||||
pub mod undo_delete;
|
pub mod undo_delete;
|
||||||
|
|
||||||
async fn send_websocket_message(
|
|
||||||
private_message_id: PrivateMessageId,
|
|
||||||
op: UserOperationCrud,
|
|
||||||
context: &LemmyContext,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
let message = blocking(context.pool(), move |conn| {
|
|
||||||
PrivateMessageView::read(conn, private_message_id)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
let res = PrivateMessageResponse {
|
|
||||||
private_message_view: message,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Send notifications to the local recipient, if one exists
|
|
||||||
let recipient_id = res.private_message_view.recipient.id;
|
|
||||||
let local_recipient_id = blocking(context.pool(), move |conn| {
|
|
||||||
LocalUserView::read_person(conn, recipient_id)
|
|
||||||
})
|
|
||||||
.await??
|
|
||||||
.local_user
|
|
||||||
.id;
|
|
||||||
|
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
|
||||||
op,
|
|
||||||
response: res,
|
|
||||||
local_recipient_id,
|
|
||||||
websocket_id: None,
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activities::{
|
activities::{
|
||||||
generate_activity_id,
|
generate_activity_id,
|
||||||
private_message::{delete::DeletePrivateMessage, send_websocket_message},
|
private_message::delete::DeletePrivateMessage,
|
||||||
verify_activity,
|
verify_activity,
|
||||||
verify_person,
|
verify_person,
|
||||||
},
|
},
|
||||||
|
@ -20,7 +20,7 @@ use lemmy_apub_lib::{
|
||||||
use lemmy_db_queries::{source::private_message::PrivateMessage_, ApubObject, Crud};
|
use lemmy_db_queries::{source::private_message::PrivateMessage_, ApubObject, Crud};
|
||||||
use lemmy_db_schema::source::{person::Person, private_message::PrivateMessage};
|
use lemmy_db_schema::source::{person::Person, private_message::PrivateMessage};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
|
@ -104,9 +104,10 @@ impl ActivityHandler for UndoDeletePrivateMessage {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
send_websocket_message(
|
send_pm_ws_message(
|
||||||
deleted_private_message.id,
|
deleted_private_message.id,
|
||||||
UserOperationCrud::EditPrivateMessage,
|
UserOperationCrud::EditPrivateMessage,
|
||||||
|
None,
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
|
@ -1,77 +1,59 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activities::{
|
activities::{
|
||||||
comment::send_websocket_message as send_comment_message,
|
deletion::{delete::receive_remove_action, verify_delete_activity},
|
||||||
community::send_websocket_message as send_community_message,
|
|
||||||
post::send_websocket_message as send_post_message,
|
|
||||||
verify_activity,
|
verify_activity,
|
||||||
verify_add_remove_moderator_target,
|
verify_add_remove_moderator_target,
|
||||||
verify_mod_action,
|
verify_mod_action,
|
||||||
verify_person_in_community,
|
verify_person_in_community,
|
||||||
},
|
},
|
||||||
fetcher::{
|
fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person},
|
||||||
community::get_or_fetch_and_upsert_community,
|
|
||||||
objects::get_or_fetch_and_insert_post_or_comment,
|
|
||||||
person::get_or_fetch_and_upsert_person,
|
|
||||||
},
|
|
||||||
CommunityType,
|
CommunityType,
|
||||||
PostOrComment,
|
|
||||||
};
|
};
|
||||||
use activitystreams::{activity::kind::RemoveType, base::AnyBase};
|
use activitystreams::{activity::kind::RemoveType, base::AnyBase};
|
||||||
use anyhow::anyhow;
|
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::{values::PublicUrl, ActivityCommonFields, ActivityHandler};
|
use lemmy_apub_lib::{values::PublicUrl, ActivityCommonFields, ActivityHandler};
|
||||||
use lemmy_db_queries::{
|
use lemmy_db_queries::Joinable;
|
||||||
source::{comment::Comment_, community::Community_, post::Post_},
|
use lemmy_db_schema::source::community::{CommunityModerator, CommunityModeratorForm};
|
||||||
Joinable,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::source::{
|
|
||||||
comment::Comment,
|
|
||||||
community::{Community, CommunityModerator, CommunityModeratorForm},
|
|
||||||
post::Post,
|
|
||||||
};
|
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{LemmyContext, UserOperationCrud};
|
use lemmy_websocket::LemmyContext;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
// TODO: we can probably deduplicate a bunch of code between this and DeletePostCommentOrCommunity
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct RemovePostCommentCommunityOrMod {
|
pub struct RemoveMod {
|
||||||
to: PublicUrl,
|
to: PublicUrl,
|
||||||
pub(in crate::activities::removal) object: Url,
|
pub(in crate::activities::removal) object: Url,
|
||||||
cc: [Url; 1],
|
cc: [Url; 1],
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: RemoveType,
|
kind: RemoveType,
|
||||||
// if target is set, this is means remove mod from community
|
// if target is set, this is means remove mod from community
|
||||||
target: Option<Url>,
|
pub(in crate::activities::removal) target: Option<Url>,
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
common: ActivityCommonFields,
|
common: ActivityCommonFields,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ActivityHandler for RemovePostCommentCommunityOrMod {
|
impl ActivityHandler for RemoveMod {
|
||||||
async fn verify(
|
async fn verify(
|
||||||
&self,
|
&self,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
verify_activity(self.common())?;
|
verify_activity(self.common())?;
|
||||||
let object_community =
|
if let Some(target) = &self.target {
|
||||||
get_or_fetch_and_upsert_community(&self.object, context, request_counter).await;
|
|
||||||
// removing a community
|
|
||||||
if object_community.is_ok() {
|
|
||||||
verify_mod_action(&self.common.actor, self.object.clone(), context).await?;
|
|
||||||
}
|
|
||||||
// removing community mod
|
|
||||||
else if let Some(target) = &self.target {
|
|
||||||
verify_person_in_community(&self.common.actor, &self.cc[0], context, request_counter).await?;
|
verify_person_in_community(&self.common.actor, &self.cc[0], context, request_counter).await?;
|
||||||
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
|
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
|
||||||
verify_add_remove_moderator_target(target, self.cc[0].clone())?;
|
verify_add_remove_moderator_target(target, self.cc[0].clone())?;
|
||||||
}
|
} else {
|
||||||
// removing a post or comment
|
verify_delete_activity(
|
||||||
else {
|
&self.object,
|
||||||
verify_person_in_community(&self.common.actor, &self.cc[0], context, request_counter).await?;
|
&self.cc[0],
|
||||||
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
|
self.common(),
|
||||||
|
true,
|
||||||
|
context,
|
||||||
|
request_counter,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -81,27 +63,7 @@ impl ActivityHandler for RemovePostCommentCommunityOrMod {
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let object_community =
|
if self.target.is_some() {
|
||||||
get_or_fetch_and_upsert_community(&self.object, context, request_counter).await;
|
|
||||||
// removing a community
|
|
||||||
if let Ok(community) = object_community {
|
|
||||||
if community.local {
|
|
||||||
return Err(anyhow!("Only local admin can remove community").into());
|
|
||||||
}
|
|
||||||
let deleted_community = blocking(context.pool(), move |conn| {
|
|
||||||
Community::update_removed(conn, community.id, true)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
send_community_message(
|
|
||||||
deleted_community.id,
|
|
||||||
UserOperationCrud::RemoveCommunity,
|
|
||||||
context,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
// removing community mod
|
|
||||||
else if self.target.is_some() {
|
|
||||||
let community =
|
let community =
|
||||||
get_or_fetch_and_upsert_community(&self.cc[0], context, request_counter).await?;
|
get_or_fetch_and_upsert_community(&self.cc[0], context, request_counter).await?;
|
||||||
let remove_mod =
|
let remove_mod =
|
||||||
|
@ -121,33 +83,17 @@ impl ActivityHandler for RemovePostCommentCommunityOrMod {
|
||||||
.await?;
|
.await?;
|
||||||
// TODO: send websocket notification about removed mod
|
// TODO: send websocket notification about removed mod
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
} else {
|
||||||
// removing a post or comment
|
receive_remove_action(
|
||||||
else {
|
&self.common.actor,
|
||||||
match get_or_fetch_and_insert_post_or_comment(&self.object, context, request_counter).await? {
|
&self.object,
|
||||||
PostOrComment::Post(post) => {
|
None,
|
||||||
let removed_post = blocking(context.pool(), move |conn| {
|
|
||||||
Post::update_removed(conn, post.id, true)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
send_post_message(removed_post.id, UserOperationCrud::EditPost, context).await
|
|
||||||
}
|
|
||||||
PostOrComment::Comment(comment) => {
|
|
||||||
let removed_comment = blocking(context.pool(), move |conn| {
|
|
||||||
Comment::update_removed(conn, comment.id, true)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
send_comment_message(
|
|
||||||
removed_comment.id,
|
|
||||||
vec![],
|
|
||||||
UserOperationCrud::EditComment,
|
|
||||||
context,
|
context,
|
||||||
|
request_counter,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn common(&self) -> &ActivityCommonFields {
|
fn common(&self) -> &ActivityCommonFields {
|
||||||
&self.common
|
&self.common
|
||||||
|
|
|
@ -1,34 +1,20 @@
|
||||||
use crate::{
|
use crate::activities::{
|
||||||
activities::{
|
deletion::{undo_delete::UndoDelete, verify_delete_activity},
|
||||||
comment::send_websocket_message as send_comment_message,
|
removal::remove::RemoveMod,
|
||||||
community::send_websocket_message as send_community_message,
|
|
||||||
post::send_websocket_message as send_post_message,
|
|
||||||
removal::remove::RemovePostCommentCommunityOrMod,
|
|
||||||
verify_activity,
|
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,
|
|
||||||
},
|
|
||||||
PostOrComment,
|
|
||||||
};
|
};
|
||||||
use activitystreams::activity::kind::UndoType;
|
use activitystreams::activity::kind::UndoType;
|
||||||
use anyhow::anyhow;
|
|
||||||
use lemmy_api_common::blocking;
|
|
||||||
use lemmy_apub_lib::{values::PublicUrl, 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;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{LemmyContext, UserOperationCrud};
|
use lemmy_websocket::LemmyContext;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct UndoRemovePostCommentOrCommunity {
|
pub struct UndoRemovePostCommentOrCommunity {
|
||||||
to: PublicUrl,
|
to: PublicUrl,
|
||||||
object: RemovePostCommentCommunityOrMod,
|
// Note, there is no such thing as Undo/Remove/Mod, so we ignore that
|
||||||
|
object: RemoveMod,
|
||||||
cc: [Url; 1],
|
cc: [Url; 1],
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: UndoType,
|
kind: UndoType,
|
||||||
|
@ -44,74 +30,26 @@ impl ActivityHandler for UndoRemovePostCommentOrCommunity {
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
verify_activity(self.common())?;
|
verify_activity(self.common())?;
|
||||||
let object_community =
|
|
||||||
get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await;
|
|
||||||
// removing a community
|
|
||||||
if object_community.is_ok() {
|
|
||||||
verify_mod_action(&self.common.actor, self.object.object.clone(), context).await?;
|
|
||||||
}
|
|
||||||
// removing a post or comment
|
|
||||||
else {
|
|
||||||
verify_person_in_community(&self.common.actor, &self.cc[0], context, request_counter).await?;
|
|
||||||
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
|
|
||||||
}
|
|
||||||
self.object.verify(context, request_counter).await?;
|
self.object.verify(context, request_counter).await?;
|
||||||
// dont check that actor and object.actor are identical, so that one mod can
|
|
||||||
// undo the action of another
|
verify_delete_activity(
|
||||||
|
&self.object.object,
|
||||||
|
&self.cc[0],
|
||||||
|
self.common(),
|
||||||
|
true,
|
||||||
|
context,
|
||||||
|
request_counter,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn receive(
|
async fn receive(
|
||||||
self,
|
self,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
_request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let object_community =
|
UndoDelete::receive_undo_remove_action(&self.object.object, context).await
|
||||||
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 {
|
|
||||||
return Err(anyhow!("Only local admin can undo remove community").into());
|
|
||||||
}
|
|
||||||
let deleted_community = blocking(context.pool(), move |conn| {
|
|
||||||
Community::update_removed(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 removed_post = blocking(context.pool(), move |conn| {
|
|
||||||
Post::update_removed(conn, post.id, false)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
send_post_message(removed_post.id, UserOperationCrud::EditPost, context).await
|
|
||||||
}
|
|
||||||
PostOrComment::Comment(comment) => {
|
|
||||||
let removed_comment = blocking(context.pool(), move |conn| {
|
|
||||||
Comment::update_removed(conn, comment.id, false)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
send_comment_message(
|
|
||||||
removed_comment.id,
|
|
||||||
vec![],
|
|
||||||
UserOperationCrud::EditComment,
|
|
||||||
context,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn common(&self) -> &ActivityCommonFields {
|
fn common(&self) -> &ActivityCommonFields {
|
||||||
|
|
|
@ -1,153 +0,0 @@
|
||||||
use crate::{
|
|
||||||
activities::generate_activity_id,
|
|
||||||
activity_queue::send_to_community,
|
|
||||||
extensions::context::lemmy_context,
|
|
||||||
ActorType,
|
|
||||||
ApubObjectType,
|
|
||||||
};
|
|
||||||
use activitystreams::{
|
|
||||||
activity::{
|
|
||||||
kind::{DeleteType, RemoveType, UndoType},
|
|
||||||
Delete,
|
|
||||||
Remove,
|
|
||||||
Undo,
|
|
||||||
},
|
|
||||||
prelude::*,
|
|
||||||
public,
|
|
||||||
};
|
|
||||||
use lemmy_api_common::blocking;
|
|
||||||
use lemmy_db_queries::Crud;
|
|
||||||
use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
|
|
||||||
use lemmy_utils::LemmyError;
|
|
||||||
use lemmy_websocket::LemmyContext;
|
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
|
||||||
impl ApubObjectType for Comment {
|
|
||||||
async fn send_delete(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
|
||||||
let post_id = self.post_id;
|
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
|
||||||
|
|
||||||
let community_id = post.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().into_inner(),
|
|
||||||
self.ap_id.to_owned().into_inner(),
|
|
||||||
);
|
|
||||||
delete
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(DeleteType::Delete)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
|
||||||
|
|
||||||
send_to_community(delete, creator, &community, None, context).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn send_undo_delete(
|
|
||||||
&self,
|
|
||||||
creator: &Person,
|
|
||||||
context: &LemmyContext,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
let post_id = self.post_id;
|
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
|
||||||
|
|
||||||
let community_id = post.community_id;
|
|
||||||
let community = blocking(context.pool(), move |conn| {
|
|
||||||
Community::read(conn, community_id)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
// Generate a fake delete activity, with the correct object
|
|
||||||
let mut delete = Delete::new(
|
|
||||||
creator.actor_id.to_owned().into_inner(),
|
|
||||||
self.ap_id.to_owned().into_inner(),
|
|
||||||
);
|
|
||||||
delete
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(DeleteType::Delete)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
|
||||||
|
|
||||||
// Undo that fake activity
|
|
||||||
let mut undo = Undo::new(
|
|
||||||
creator.actor_id.to_owned().into_inner(),
|
|
||||||
delete.into_any_base()?,
|
|
||||||
);
|
|
||||||
undo
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(UndoType::Undo)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
|
||||||
|
|
||||||
send_to_community(undo, creator, &community, None, context).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn send_remove(&self, mod_: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
|
||||||
let post_id = self.post_id;
|
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
|
||||||
|
|
||||||
let community_id = post.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().into_inner(),
|
|
||||||
self.ap_id.to_owned().into_inner(),
|
|
||||||
);
|
|
||||||
remove
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(RemoveType::Remove)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
|
||||||
|
|
||||||
send_to_community(remove, mod_, &community, None, context).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn send_undo_remove(
|
|
||||||
&self,
|
|
||||||
mod_: &Person,
|
|
||||||
context: &LemmyContext,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
let post_id = self.post_id;
|
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
|
||||||
|
|
||||||
let community_id = post.community_id;
|
|
||||||
let community = blocking(context.pool(), move |conn| {
|
|
||||||
Community::read(conn, community_id)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
// Generate a fake delete activity, with the correct object
|
|
||||||
let mut remove = Remove::new(
|
|
||||||
mod_.actor_id.to_owned().into_inner(),
|
|
||||||
self.ap_id.to_owned().into_inner(),
|
|
||||||
);
|
|
||||||
remove
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(RemoveType::Remove)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
|
||||||
|
|
||||||
// Undo that fake activity
|
|
||||||
let mut undo = Undo::new(
|
|
||||||
mod_.actor_id.to_owned().into_inner(),
|
|
||||||
remove.into_any_base()?,
|
|
||||||
);
|
|
||||||
undo
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(UndoType::Undo)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
|
||||||
|
|
||||||
send_to_community(undo, mod_, &community, None, context).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,20 +12,10 @@ use crate::{
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
activity::{
|
activity::{
|
||||||
kind::{
|
kind::{AddType, AnnounceType, BlockType, RemoveType, UndoType, UpdateType},
|
||||||
AddType,
|
|
||||||
AnnounceType,
|
|
||||||
BlockType,
|
|
||||||
DeleteType,
|
|
||||||
LikeType,
|
|
||||||
RemoveType,
|
|
||||||
UndoType,
|
|
||||||
UpdateType,
|
|
||||||
},
|
|
||||||
Add,
|
Add,
|
||||||
Announce,
|
Announce,
|
||||||
Block,
|
Block,
|
||||||
Delete,
|
|
||||||
OptTargetRefExt,
|
OptTargetRefExt,
|
||||||
Remove,
|
Remove,
|
||||||
Undo,
|
Undo,
|
||||||
|
@ -97,112 +87,6 @@ impl CommunityType for Community {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the creator of a community deletes the community, send this to all followers.
|
|
||||||
///
|
|
||||||
/// We need to handle deletion by a remote mod separately.
|
|
||||||
async fn send_delete(&self, mod_: Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
|
||||||
// Local mod, send directly from community to followers
|
|
||||||
if self.local {
|
|
||||||
let mut delete = Delete::new(self.actor_id(), self.actor_id());
|
|
||||||
delete
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(DeleteType::Delete)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![self.followers_url()]);
|
|
||||||
|
|
||||||
send_to_community_followers(delete, self, None, context).await?;
|
|
||||||
}
|
|
||||||
// Remote mod, send from mod to community
|
|
||||||
else {
|
|
||||||
let mut delete = Delete::new(mod_.actor_id(), self.actor_id());
|
|
||||||
delete
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(DeleteType::Delete)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![self.actor_id()]);
|
|
||||||
|
|
||||||
send_to_community(delete, &mod_, self, None, context).await?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If the creator of a community reverts the deletion of a community, send this to all followers.
|
|
||||||
///
|
|
||||||
/// We need to handle undelete by a remote mod separately.
|
|
||||||
async fn send_undo_delete(&self, mod_: Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
|
||||||
// Local mod, send directly from community to followers
|
|
||||||
if self.local {
|
|
||||||
let mut delete = Delete::new(self.actor_id(), self.actor_id());
|
|
||||||
delete
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(DeleteType::Delete)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![self.followers_url()]);
|
|
||||||
|
|
||||||
let mut undo = Undo::new(self.actor_id(), delete.into_any_base()?);
|
|
||||||
undo
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(UndoType::Undo)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![self.followers_url()]);
|
|
||||||
|
|
||||||
send_to_community_followers(undo, self, None, context).await?;
|
|
||||||
}
|
|
||||||
// Remote mod, send from mod to community
|
|
||||||
else {
|
|
||||||
let mut delete = Delete::new(mod_.actor_id(), self.actor_id());
|
|
||||||
delete
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(DeleteType::Delete)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![self.actor_id()]);
|
|
||||||
|
|
||||||
let mut undo = Undo::new(mod_.actor_id(), delete.into_any_base()?);
|
|
||||||
undo
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(UndoType::Undo)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![self.actor_id()]);
|
|
||||||
|
|
||||||
send_to_community(undo, &mod_, self, None, context).await?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If an admin removes a community, send this to all followers.
|
|
||||||
async fn send_remove(&self, context: &LemmyContext) -> Result<(), LemmyError> {
|
|
||||||
let mut remove = Remove::new(self.actor_id(), self.actor_id());
|
|
||||||
remove
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(RemoveType::Remove)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![self.followers_url()]);
|
|
||||||
|
|
||||||
send_to_community_followers(remove, self, None, context).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If an admin reverts the removal of a community, send this to all followers.
|
|
||||||
async fn send_undo_remove(&self, context: &LemmyContext) -> Result<(), LemmyError> {
|
|
||||||
let mut remove = Remove::new(self.actor_id(), self.actor_id());
|
|
||||||
remove
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(RemoveType::Remove)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![self.followers_url()]);
|
|
||||||
|
|
||||||
// Undo that fake activity
|
|
||||||
let mut undo = Undo::new(self.actor_id(), remove.into_any_base()?);
|
|
||||||
undo
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(LikeType::Like)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![self.followers_url()]);
|
|
||||||
|
|
||||||
send_to_community_followers(undo, self, None, context).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wraps an activity sent to the community in an announce, and then sends the announce to all
|
/// Wraps an activity sent to the community in an announce, and then sends the announce to all
|
||||||
/// community followers.
|
/// community followers.
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,4 +1,2 @@
|
||||||
pub(crate) mod comment;
|
|
||||||
pub(crate) mod community;
|
pub(crate) mod community;
|
||||||
pub(crate) mod person;
|
pub(crate) mod person;
|
||||||
pub(crate) mod post;
|
|
||||||
|
|
|
@ -1,139 +0,0 @@
|
||||||
use crate::{
|
|
||||||
activities::generate_activity_id,
|
|
||||||
activity_queue::send_to_community,
|
|
||||||
extensions::context::lemmy_context,
|
|
||||||
ActorType,
|
|
||||||
ApubObjectType,
|
|
||||||
};
|
|
||||||
use activitystreams::{
|
|
||||||
activity::{
|
|
||||||
kind::{DeleteType, RemoveType, UndoType},
|
|
||||||
Delete,
|
|
||||||
Remove,
|
|
||||||
Undo,
|
|
||||||
},
|
|
||||||
prelude::*,
|
|
||||||
public,
|
|
||||||
};
|
|
||||||
use lemmy_api_common::blocking;
|
|
||||||
use lemmy_db_queries::Crud;
|
|
||||||
use lemmy_db_schema::source::{community::Community, person::Person, post::Post};
|
|
||||||
use lemmy_utils::LemmyError;
|
|
||||||
use lemmy_websocket::LemmyContext;
|
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
|
||||||
impl ApubObjectType for Post {
|
|
||||||
async fn send_delete(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
|
||||||
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().into_inner(),
|
|
||||||
self.ap_id.to_owned().into_inner(),
|
|
||||||
);
|
|
||||||
delete
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(DeleteType::Delete)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
|
||||||
|
|
||||||
send_to_community(delete, creator, &community, None, context).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn send_undo_delete(
|
|
||||||
&self,
|
|
||||||
creator: &Person,
|
|
||||||
context: &LemmyContext,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
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().into_inner(),
|
|
||||||
self.ap_id.to_owned().into_inner(),
|
|
||||||
);
|
|
||||||
delete
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(DeleteType::Delete)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
|
||||||
|
|
||||||
// Undo that fake activity
|
|
||||||
let mut undo = Undo::new(
|
|
||||||
creator.actor_id.to_owned().into_inner(),
|
|
||||||
delete.into_any_base()?,
|
|
||||||
);
|
|
||||||
undo
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(UndoType::Undo)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
|
||||||
|
|
||||||
send_to_community(undo, creator, &community, None, context).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn send_remove(&self, mod_: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
|
||||||
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().into_inner(),
|
|
||||||
self.ap_id.to_owned().into_inner(),
|
|
||||||
);
|
|
||||||
remove
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(RemoveType::Remove)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
|
||||||
|
|
||||||
send_to_community(remove, mod_, &community, None, context).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn send_undo_remove(
|
|
||||||
&self,
|
|
||||||
mod_: &Person,
|
|
||||||
context: &LemmyContext,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
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().into_inner(),
|
|
||||||
self.ap_id.to_owned().into_inner(),
|
|
||||||
);
|
|
||||||
remove
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(RemoveType::Remove)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
|
||||||
|
|
||||||
// Undo that fake activity
|
|
||||||
let mut undo = Undo::new(
|
|
||||||
mod_.actor_id.to_owned().into_inner(),
|
|
||||||
remove.into_any_base()?,
|
|
||||||
);
|
|
||||||
undo
|
|
||||||
.set_many_contexts(lemmy_context())
|
|
||||||
.set_id(generate_activity_id(UndoType::Undo)?)
|
|
||||||
.set_to(public())
|
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
|
||||||
|
|
||||||
send_to_community(undo, mod_, &community, None, context).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +1,4 @@
|
||||||
use crate::activities::{
|
use crate::activities::voting::vote::VoteType;
|
||||||
comment::send_websocket_message as send_comment_message,
|
|
||||||
post::send_websocket_message as send_post_message,
|
|
||||||
voting::vote::VoteType,
|
|
||||||
};
|
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_db_queries::Likeable;
|
use lemmy_db_queries::Likeable;
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
|
@ -11,7 +7,11 @@ use lemmy_db_schema::source::{
|
||||||
post::{Post, PostLike, PostLikeForm},
|
post::{Post, PostLike, PostLikeForm},
|
||||||
};
|
};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{LemmyContext, UserOperation};
|
use lemmy_websocket::{
|
||||||
|
send::{send_comment_ws_message_simple, send_post_ws_message},
|
||||||
|
LemmyContext,
|
||||||
|
UserOperation,
|
||||||
|
};
|
||||||
|
|
||||||
pub mod undo_vote;
|
pub mod undo_vote;
|
||||||
pub mod vote;
|
pub mod vote;
|
||||||
|
@ -36,13 +36,8 @@ async fn vote_comment(
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
send_comment_message(
|
send_comment_ws_message_simple(comment_id, UserOperation::CreateCommentLike, context).await?;
|
||||||
comment_id,
|
Ok(())
|
||||||
vec![],
|
|
||||||
UserOperation::CreateCommentLike,
|
|
||||||
context,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn vote_post(
|
async fn vote_post(
|
||||||
|
@ -64,7 +59,8 @@ async fn vote_post(
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
send_post_message(post.id, UserOperation::CreatePostLike, context).await
|
send_post_ws_message(post.id, UserOperation::CreatePostLike, None, None, context).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn undo_vote_comment(
|
async fn undo_vote_comment(
|
||||||
|
@ -79,13 +75,8 @@ async fn undo_vote_comment(
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
send_comment_message(
|
send_comment_ws_message_simple(comment_id, UserOperation::CreateCommentLike, context).await?;
|
||||||
comment.id,
|
Ok(())
|
||||||
vec![],
|
|
||||||
UserOperation::CreateCommentLike,
|
|
||||||
context,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn undo_vote_post(
|
async fn undo_vote_post(
|
||||||
|
@ -99,5 +90,7 @@ async fn undo_vote_post(
|
||||||
PostLike::remove(conn, person_id, post_id)
|
PostLike::remove(conn, person_id, post_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
send_post_message(post.id, UserOperation::CreatePostLike, context).await
|
|
||||||
|
send_post_ws_message(post_id, UserOperation::CreatePostLike, None, None, context).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use activitystreams::{base::AnyBase, context, primitives::OneOrMany};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub fn lemmy_context() -> OneOrMany<AnyBase> {
|
pub(crate) fn lemmy_context() -> OneOrMany<AnyBase> {
|
||||||
let context_ext = AnyBase::from_arbitrary_json(json!(
|
let context_ext = AnyBase::from_arbitrary_json(json!(
|
||||||
{
|
{
|
||||||
"sc": "http://schema.org#",
|
"sc": "http://schema.org#",
|
||||||
|
|
|
@ -62,7 +62,7 @@ pub(crate) async fn sign_and_send(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verifies the HTTP signature on an incoming inbox request.
|
/// Verifies the HTTP signature on an incoming inbox request.
|
||||||
pub fn verify_signature(request: &HttpRequest, public_key: &str) -> Result<(), LemmyError> {
|
pub(crate) fn verify_signature(request: &HttpRequest, public_key: &str) -> Result<(), LemmyError> {
|
||||||
let verified = CONFIG2
|
let verified = CONFIG2
|
||||||
.begin_verify(
|
.begin_verify(
|
||||||
request.method(),
|
request.method(),
|
||||||
|
|
|
@ -25,7 +25,7 @@ use url::Url;
|
||||||
///
|
///
|
||||||
/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
|
/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
|
||||||
/// Otherwise it is fetched from the remote instance, stored and returned.
|
/// Otherwise it is fetched from the remote instance, stored and returned.
|
||||||
pub async fn get_or_fetch_and_upsert_community(
|
pub(crate) async fn get_or_fetch_and_upsert_community(
|
||||||
apub_id: &Url,
|
apub_id: &Url,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
recursion_counter: &mut i32,
|
recursion_counter: &mut i32,
|
||||||
|
|
|
@ -42,7 +42,7 @@ where
|
||||||
///
|
///
|
||||||
/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
|
/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
|
||||||
/// Otherwise it is fetched from the remote instance, stored and returned.
|
/// Otherwise it is fetched from the remote instance, stored and returned.
|
||||||
pub async fn get_or_fetch_and_upsert_actor(
|
pub(crate) async fn get_or_fetch_and_upsert_actor(
|
||||||
apub_id: &Url,
|
apub_id: &Url,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
recursion_counter: &mut i32,
|
recursion_counter: &mut i32,
|
||||||
|
|
|
@ -17,7 +17,7 @@ use url::Url;
|
||||||
/// pulled from its apub ID, inserted and returned.
|
/// pulled from its apub ID, inserted and returned.
|
||||||
///
|
///
|
||||||
/// The parent community is also pulled if necessary. Comments are not pulled.
|
/// The parent community is also pulled if necessary. Comments are not pulled.
|
||||||
pub async fn get_or_fetch_and_insert_post(
|
pub(crate) async fn get_or_fetch_and_insert_post(
|
||||||
post_ap_id: &Url,
|
post_ap_id: &Url,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
recursion_counter: &mut i32,
|
recursion_counter: &mut i32,
|
||||||
|
@ -46,7 +46,7 @@ pub async fn get_or_fetch_and_insert_post(
|
||||||
/// pulled from its apub ID, inserted and returned.
|
/// pulled from its apub ID, inserted and returned.
|
||||||
///
|
///
|
||||||
/// The parent community, post and comment are also pulled if necessary.
|
/// The parent community, post and comment are also pulled if necessary.
|
||||||
pub async fn get_or_fetch_and_insert_comment(
|
pub(crate) async fn get_or_fetch_and_insert_comment(
|
||||||
comment_ap_id: &Url,
|
comment_ap_id: &Url,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
recursion_counter: &mut i32,
|
recursion_counter: &mut i32,
|
||||||
|
@ -80,7 +80,7 @@ pub async fn get_or_fetch_and_insert_comment(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_or_fetch_and_insert_post_or_comment(
|
pub(crate) async fn get_or_fetch_and_insert_post_or_comment(
|
||||||
ap_id: &Url,
|
ap_id: &Url,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
recursion_counter: &mut i32,
|
recursion_counter: &mut i32,
|
||||||
|
|
|
@ -16,7 +16,7 @@ use url::Url;
|
||||||
///
|
///
|
||||||
/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
|
/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
|
||||||
/// Otherwise it is fetched from the remote instance, stored and returned.
|
/// Otherwise it is fetched from the remote instance, stored and returned.
|
||||||
pub async fn get_or_fetch_and_upsert_person(
|
pub(crate) async fn get_or_fetch_and_upsert_person(
|
||||||
apub_id: &Url,
|
apub_id: &Url,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
recursion_counter: &mut i32,
|
recursion_counter: &mut i32,
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::activities::{
|
||||||
undo_block_user::UndoBlockUserFromCommunity,
|
undo_block_user::UndoBlockUserFromCommunity,
|
||||||
update::UpdateCommunity,
|
update::UpdateCommunity,
|
||||||
},
|
},
|
||||||
deletion::{delete::DeletePostCommentOrCommunity, undo_delete::UndoDeletePostCommentOrCommunity},
|
deletion::{delete::Delete, undo_delete::UndoDelete},
|
||||||
following::{accept::AcceptFollowCommunity, follow::FollowCommunity, undo::UndoFollowCommunity},
|
following::{accept::AcceptFollowCommunity, follow::FollowCommunity, undo::UndoFollowCommunity},
|
||||||
post::create_or_update::CreateOrUpdatePost,
|
post::create_or_update::CreateOrUpdatePost,
|
||||||
private_message::{
|
private_message::{
|
||||||
|
@ -15,10 +15,7 @@ use crate::activities::{
|
||||||
delete::DeletePrivateMessage,
|
delete::DeletePrivateMessage,
|
||||||
undo_delete::UndoDeletePrivateMessage,
|
undo_delete::UndoDeletePrivateMessage,
|
||||||
},
|
},
|
||||||
removal::{
|
removal::{remove::RemoveMod, undo_remove::UndoRemovePostCommentOrCommunity},
|
||||||
remove::RemovePostCommentCommunityOrMod,
|
|
||||||
undo_remove::UndoRemovePostCommentOrCommunity,
|
|
||||||
},
|
|
||||||
voting::{undo_vote::UndoVote, vote::Vote},
|
voting::{undo_vote::UndoVote, vote::Vote},
|
||||||
};
|
};
|
||||||
use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler};
|
use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler};
|
||||||
|
@ -45,14 +42,14 @@ pub enum GroupInboxActivities {
|
||||||
CreateOrUpdatePost(Box<CreateOrUpdatePost>),
|
CreateOrUpdatePost(Box<CreateOrUpdatePost>),
|
||||||
Vote(Vote),
|
Vote(Vote),
|
||||||
UndoVote(UndoVote),
|
UndoVote(UndoVote),
|
||||||
DeletePostCommentOrCommunity(DeletePostCommentOrCommunity),
|
DeletePostCommentOrCommunity(Delete),
|
||||||
UndoDeletePostCommentOrCommunity(UndoDeletePostCommentOrCommunity),
|
UndoDeletePostCommentOrCommunity(UndoDelete),
|
||||||
RemovePostCommentOrCommunity(RemovePostCommentCommunityOrMod),
|
|
||||||
UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
|
UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
|
||||||
UpdateCommunity(Box<UpdateCommunity>),
|
UpdateCommunity(Box<UpdateCommunity>),
|
||||||
BlockUserFromCommunity(BlockUserFromCommunity),
|
BlockUserFromCommunity(BlockUserFromCommunity),
|
||||||
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
|
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
|
||||||
AddMod(AddMod),
|
AddMod(AddMod),
|
||||||
|
RemoveMod(RemoveMod),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
|
||||||
|
@ -65,14 +62,14 @@ pub enum SharedInboxActivities {
|
||||||
CreateOrUpdatePost(Box<CreateOrUpdatePost>),
|
CreateOrUpdatePost(Box<CreateOrUpdatePost>),
|
||||||
Vote(Vote),
|
Vote(Vote),
|
||||||
UndoVote(UndoVote),
|
UndoVote(UndoVote),
|
||||||
DeletePostCommentOrCommunity(DeletePostCommentOrCommunity),
|
Delete(Delete),
|
||||||
UndoDeletePostCommentOrCommunity(UndoDeletePostCommentOrCommunity),
|
UndoDelete(UndoDelete),
|
||||||
RemovePostCommentOrCommunity(RemovePostCommentCommunityOrMod),
|
|
||||||
UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
|
UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
|
||||||
UpdateCommunity(Box<UpdateCommunity>),
|
UpdateCommunity(Box<UpdateCommunity>),
|
||||||
BlockUserFromCommunity(BlockUserFromCommunity),
|
BlockUserFromCommunity(BlockUserFromCommunity),
|
||||||
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
|
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
|
||||||
AddMod(AddMod),
|
AddMod(AddMod),
|
||||||
|
RemoveMod(RemoveMod),
|
||||||
// received by person
|
// received by person
|
||||||
AcceptFollowCommunity(AcceptFollowCommunity),
|
AcceptFollowCommunity(AcceptFollowCommunity),
|
||||||
// Note, pm activities need to be at the end, otherwise comments will end up here. We can probably
|
// Note, pm activities need to be at the end, otherwise comments will end up here. We can probably
|
||||||
|
|
|
@ -34,7 +34,7 @@ use serde::Serialize;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
use url::{ParseError, Url};
|
use url::{ParseError, Url};
|
||||||
|
|
||||||
pub static APUB_JSON_CONTENT_TYPE: &str = "application/activity+json";
|
static APUB_JSON_CONTENT_TYPE: &str = "application/activity+json";
|
||||||
|
|
||||||
/// Checks if the ID is allowed for sending or receiving.
|
/// Checks if the ID is allowed for sending or receiving.
|
||||||
///
|
///
|
||||||
|
@ -102,28 +102,9 @@ pub(crate) fn check_is_apub_id_valid(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Common functions for ActivityPub objects, which are implemented by most (but not all) objects
|
|
||||||
/// and actors in Lemmy.
|
|
||||||
#[async_trait::async_trait(?Send)]
|
|
||||||
pub trait ApubObjectType {
|
|
||||||
async fn send_delete(&self, creator: &DbPerson, context: &LemmyContext)
|
|
||||||
-> Result<(), LemmyError>;
|
|
||||||
async fn send_undo_delete(
|
|
||||||
&self,
|
|
||||||
creator: &DbPerson,
|
|
||||||
context: &LemmyContext,
|
|
||||||
) -> Result<(), LemmyError>;
|
|
||||||
async fn send_remove(&self, mod_: &DbPerson, context: &LemmyContext) -> Result<(), LemmyError>;
|
|
||||||
async fn send_undo_remove(
|
|
||||||
&self,
|
|
||||||
mod_: &DbPerson,
|
|
||||||
context: &LemmyContext,
|
|
||||||
) -> Result<(), LemmyError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Common methods provided by ActivityPub actors (community and person). Not all methods are
|
/// Common methods provided by ActivityPub actors (community and person). Not all methods are
|
||||||
/// implemented by all actors.
|
/// implemented by all actors.
|
||||||
pub trait ActorType {
|
trait ActorType {
|
||||||
fn is_local(&self) -> bool;
|
fn is_local(&self) -> bool;
|
||||||
fn actor_id(&self) -> Url;
|
fn actor_id(&self) -> Url;
|
||||||
fn name(&self) -> String;
|
fn name(&self) -> String;
|
||||||
|
@ -160,11 +141,6 @@ pub trait CommunityType {
|
||||||
async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<Url>, LemmyError>;
|
async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<Url>, LemmyError>;
|
||||||
|
|
||||||
async fn send_update(&self, mod_: Person, context: &LemmyContext) -> Result<(), LemmyError>;
|
async fn send_update(&self, mod_: Person, context: &LemmyContext) -> Result<(), LemmyError>;
|
||||||
async fn send_delete(&self, mod_: Person, context: &LemmyContext) -> Result<(), LemmyError>;
|
|
||||||
async fn send_undo_delete(&self, mod_: Person, context: &LemmyContext) -> Result<(), LemmyError>;
|
|
||||||
|
|
||||||
async fn send_remove(&self, context: &LemmyContext) -> Result<(), LemmyError>;
|
|
||||||
async fn send_undo_remove(&self, context: &LemmyContext) -> Result<(), LemmyError>;
|
|
||||||
|
|
||||||
async fn send_announce(
|
async fn send_announce(
|
||||||
&self,
|
&self,
|
||||||
|
@ -209,7 +185,7 @@ pub enum EndpointType {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates an apub endpoint for a given domain, IE xyz.tld
|
/// Generates an apub endpoint for a given domain, IE xyz.tld
|
||||||
pub(crate) fn generate_apub_endpoint_for_domain(
|
fn generate_apub_endpoint_for_domain(
|
||||||
endpoint_type: EndpointType,
|
endpoint_type: EndpointType,
|
||||||
name: &str,
|
name: &str,
|
||||||
domain: &str,
|
domain: &str,
|
||||||
|
@ -260,7 +236,7 @@ pub fn generate_shared_inbox_url(actor_id: &DbUrl) -> Result<DbUrl, LemmyError>
|
||||||
Ok(Url::parse(&url)?.into())
|
Ok(Url::parse(&url)?.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_moderators_url(community_id: &DbUrl) -> Result<DbUrl, LemmyError> {
|
fn generate_moderators_url(community_id: &DbUrl) -> Result<DbUrl, LemmyError> {
|
||||||
Ok(Url::parse(&format!("{}/moderators", community_id))?.into())
|
Ok(Url::parse(&format!("{}/moderators", community_id))?.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +262,7 @@ pub fn build_actor_id_from_shortname(
|
||||||
|
|
||||||
/// Store a sent or received activity in the database, for logging purposes. These records are not
|
/// Store a sent or received activity in the database, for logging purposes. These records are not
|
||||||
/// persistent.
|
/// persistent.
|
||||||
pub(crate) async fn insert_activity<T>(
|
async fn insert_activity<T>(
|
||||||
ap_id: &Url,
|
ap_id: &Url,
|
||||||
activity: T,
|
activity: T,
|
||||||
local: bool,
|
local: bool,
|
||||||
|
@ -348,7 +324,7 @@ pub(crate) async fn find_post_or_comment_by_id(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Object {
|
enum Object {
|
||||||
Comment(Box<Comment>),
|
Comment(Box<Comment>),
|
||||||
Post(Box<Post>),
|
Post(Box<Post>),
|
||||||
Community(Box<Community>),
|
Community(Box<Community>),
|
||||||
|
@ -356,10 +332,7 @@ pub enum Object {
|
||||||
PrivateMessage(Box<PrivateMessage>),
|
PrivateMessage(Box<PrivateMessage>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn find_object_by_id(
|
async fn find_object_by_id(context: &LemmyContext, apub_id: Url) -> Result<Object, LemmyError> {
|
||||||
context: &LemmyContext,
|
|
||||||
apub_id: Url,
|
|
||||||
) -> Result<Object, LemmyError> {
|
|
||||||
let ap_id = apub_id.clone();
|
let ap_id = apub_id.clone();
|
||||||
if let Ok(pc) = find_post_or_comment_by_id(context, ap_id.to_owned()).await {
|
if let Ok(pc) = find_post_or_comment_by_id(context, ap_id.to_owned()).await {
|
||||||
return Ok(match pc {
|
return Ok(match pc {
|
||||||
|
@ -397,7 +370,7 @@ pub(crate) async fn find_object_by_id(
|
||||||
Err(NotFound.into())
|
Err(NotFound.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn check_community_or_site_ban(
|
async fn check_community_or_site_ban(
|
||||||
person: &Person,
|
person: &Person,
|
||||||
community_id: CommunityId,
|
community_id: CommunityId,
|
||||||
pool: &DbPool,
|
pool: &DbPool,
|
||||||
|
|
|
@ -15,3 +15,15 @@ pub enum CommentInReplyToMigration {
|
||||||
Old(Vec<Url>),
|
Old(Vec<Url>),
|
||||||
New(Url),
|
New(Url),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Another migration we are doing is to handle all deletions and removals using Delete activity.
|
||||||
|
// This is because Remove is for removing an object from a collection, so using it that way doesn't
|
||||||
|
// really make sense. It is also a problem because we have a RemoveMod activity, which was awkward
|
||||||
|
// to handle together with removing posts etc.
|
||||||
|
//
|
||||||
|
// v0.11: send and receive mod removals as Remove
|
||||||
|
// v0.12: receive removals as Remove, send as Delete (compatible with v0.11)
|
||||||
|
// v0.13: send and receive mod removals as Delete (compatible with v0.12)
|
||||||
|
//
|
||||||
|
// For v0.13, delete [`UndoRemovePostCommentOrCommunity`], and don't handle object deletion in
|
||||||
|
// [`RemoveMod`] handler.
|
||||||
|
|
|
@ -19,14 +19,14 @@ pub(crate) mod private_message;
|
||||||
|
|
||||||
/// Trait for converting an object or actor into the respective ActivityPub type.
|
/// Trait for converting an object or actor into the respective ActivityPub type.
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
pub trait ToApub {
|
pub(crate) trait ToApub {
|
||||||
type ApubType;
|
type ApubType;
|
||||||
async fn to_apub(&self, pool: &DbPool) -> Result<Self::ApubType, LemmyError>;
|
async fn to_apub(&self, pool: &DbPool) -> Result<Self::ApubType, LemmyError>;
|
||||||
fn to_tombstone(&self) -> Result<Tombstone, LemmyError>;
|
fn to_tombstone(&self) -> Result<Tombstone, LemmyError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
pub trait FromApub {
|
pub(crate) trait FromApub {
|
||||||
type ApubType;
|
type ApubType;
|
||||||
/// Converts an object from ActivityPub type to Lemmy internal type.
|
/// Converts an object from ActivityPub type to Lemmy internal type.
|
||||||
///
|
///
|
||||||
|
|
|
@ -25,17 +25,19 @@ pub mod source;
|
||||||
|
|
||||||
pub type DbPool = diesel::r2d2::Pool<diesel::r2d2::ConnectionManager<diesel::PgConnection>>;
|
pub type DbPool = diesel::r2d2::Pool<diesel::r2d2::ConnectionManager<diesel::PgConnection>>;
|
||||||
|
|
||||||
pub trait Crud<Form, IdType> {
|
pub trait Crud {
|
||||||
fn create(conn: &PgConnection, form: &Form) -> Result<Self, Error>
|
type Form;
|
||||||
|
type IdType;
|
||||||
|
fn create(conn: &PgConnection, form: &Self::Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn read(conn: &PgConnection, id: IdType) -> Result<Self, Error>
|
fn read(conn: &PgConnection, id: Self::IdType) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn update(conn: &PgConnection, id: IdType, form: &Form) -> Result<Self, Error>
|
fn update(conn: &PgConnection, id: Self::IdType, form: &Self::Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn delete(_conn: &PgConnection, _id: IdType) -> Result<usize, Error>
|
fn delete(_conn: &PgConnection, _id: Self::IdType) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
@ -43,8 +45,9 @@ pub trait Crud<Form, IdType> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Followable<Form> {
|
pub trait Followable {
|
||||||
fn follow(conn: &PgConnection, form: &Form) -> Result<Self, Error>
|
type Form;
|
||||||
|
fn follow(conn: &PgConnection, form: &Self::Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn follow_accepted(
|
fn follow_accepted(
|
||||||
|
@ -54,59 +57,70 @@ pub trait Followable<Form> {
|
||||||
) -> Result<Self, Error>
|
) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn unfollow(conn: &PgConnection, form: &Form) -> Result<usize, Error>
|
fn unfollow(conn: &PgConnection, form: &Self::Form) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn has_local_followers(conn: &PgConnection, community_id: CommunityId) -> Result<bool, Error>;
|
fn has_local_followers(conn: &PgConnection, community_id: CommunityId) -> Result<bool, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Joinable<Form> {
|
pub trait Joinable {
|
||||||
fn join(conn: &PgConnection, form: &Form) -> Result<Self, Error>
|
type Form;
|
||||||
|
fn join(conn: &PgConnection, form: &Self::Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn leave(conn: &PgConnection, form: &Form) -> Result<usize, Error>
|
fn leave(conn: &PgConnection, form: &Self::Form) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Likeable<Form, IdType> {
|
pub trait Likeable {
|
||||||
fn like(conn: &PgConnection, form: &Form) -> Result<Self, Error>
|
type Form;
|
||||||
|
type IdType;
|
||||||
|
fn like(conn: &PgConnection, form: &Self::Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn remove(conn: &PgConnection, person_id: PersonId, item_id: IdType) -> Result<usize, Error>
|
fn remove(
|
||||||
|
conn: &PgConnection,
|
||||||
|
person_id: PersonId,
|
||||||
|
item_id: Self::IdType,
|
||||||
|
) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Bannable<Form> {
|
pub trait Bannable {
|
||||||
fn ban(conn: &PgConnection, form: &Form) -> Result<Self, Error>
|
type Form;
|
||||||
|
fn ban(conn: &PgConnection, form: &Self::Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn unban(conn: &PgConnection, form: &Form) -> Result<usize, Error>
|
fn unban(conn: &PgConnection, form: &Self::Form) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Saveable<Form> {
|
pub trait Saveable {
|
||||||
fn save(conn: &PgConnection, form: &Form) -> Result<Self, Error>
|
type Form;
|
||||||
|
fn save(conn: &PgConnection, form: &Self::Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn unsave(conn: &PgConnection, form: &Form) -> Result<usize, Error>
|
fn unsave(conn: &PgConnection, form: &Self::Form) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Readable<Form> {
|
pub trait Readable {
|
||||||
fn mark_as_read(conn: &PgConnection, form: &Form) -> Result<Self, Error>
|
type Form;
|
||||||
|
fn mark_as_read(conn: &PgConnection, form: &Self::Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn mark_as_unread(conn: &PgConnection, form: &Form) -> Result<usize, Error>
|
fn mark_as_unread(conn: &PgConnection, form: &Self::Form) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Reportable<Form> {
|
pub trait Reportable {
|
||||||
fn report(conn: &PgConnection, form: &Form) -> Result<Self, Error>
|
type Form;
|
||||||
|
fn report(conn: &PgConnection, form: &Self::Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn resolve(conn: &PgConnection, report_id: i32, resolver_id: PersonId) -> Result<usize, Error>
|
fn resolve(conn: &PgConnection, report_id: i32, resolver_id: PersonId) -> Result<usize, Error>
|
||||||
|
@ -121,11 +135,12 @@ pub trait DeleteableOrRemoveable {
|
||||||
fn blank_out_deleted_or_removed_info(self) -> Self;
|
fn blank_out_deleted_or_removed_info(self) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ApubObject<Form> {
|
pub trait ApubObject {
|
||||||
|
type Form;
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error>
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn upsert(conn: &PgConnection, user_form: &Form) -> Result<Self, Error>
|
fn upsert(conn: &PgConnection, user_form: &Self::Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,9 @@ use std::{
|
||||||
io::{Error as IoError, ErrorKind},
|
io::{Error as IoError, ErrorKind},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Crud<ActivityForm, i32> for Activity {
|
impl Crud for Activity {
|
||||||
|
type Form = ActivityForm;
|
||||||
|
type IdType = i32;
|
||||||
fn read(conn: &PgConnection, activity_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, activity_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::activity::dsl::*;
|
use lemmy_db_schema::schema::activity::dsl::*;
|
||||||
activity.find(activity_id).first::<Self>(conn)
|
activity.find(activity_id).first::<Self>(conn)
|
||||||
|
|
|
@ -135,7 +135,9 @@ impl Comment_ for Comment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<CommentForm, CommentId> for Comment {
|
impl Crud for Comment {
|
||||||
|
type Form = CommentForm;
|
||||||
|
type IdType = CommentId;
|
||||||
fn read(conn: &PgConnection, comment_id: CommentId) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, comment_id: CommentId) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::comment::dsl::*;
|
use lemmy_db_schema::schema::comment::dsl::*;
|
||||||
comment.find(comment_id).first::<Self>(conn)
|
comment.find(comment_id).first::<Self>(conn)
|
||||||
|
@ -165,7 +167,8 @@ impl Crud<CommentForm, CommentId> for Comment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApubObject<CommentForm> for Comment {
|
impl ApubObject for Comment {
|
||||||
|
type Form = CommentForm;
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error> {
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::comment::dsl::*;
|
use lemmy_db_schema::schema::comment::dsl::*;
|
||||||
comment.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
comment.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
||||||
|
@ -182,7 +185,9 @@ impl ApubObject<CommentForm> for Comment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Likeable<CommentLikeForm, CommentId> for CommentLike {
|
impl Likeable for CommentLike {
|
||||||
|
type Form = CommentLikeForm;
|
||||||
|
type IdType = CommentId;
|
||||||
fn like(conn: &PgConnection, comment_like_form: &CommentLikeForm) -> Result<Self, Error> {
|
fn like(conn: &PgConnection, comment_like_form: &CommentLikeForm) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::comment_like::dsl::*;
|
use lemmy_db_schema::schema::comment_like::dsl::*;
|
||||||
insert_into(comment_like)
|
insert_into(comment_like)
|
||||||
|
@ -207,7 +212,8 @@ impl Likeable<CommentLikeForm, CommentId> for CommentLike {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Saveable<CommentSavedForm> for CommentSaved {
|
impl Saveable for CommentSaved {
|
||||||
|
type Form = CommentSavedForm;
|
||||||
fn save(conn: &PgConnection, comment_saved_form: &CommentSavedForm) -> Result<Self, Error> {
|
fn save(conn: &PgConnection, comment_saved_form: &CommentSavedForm) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::comment_saved::dsl::*;
|
use lemmy_db_schema::schema::comment_saved::dsl::*;
|
||||||
insert_into(comment_saved)
|
insert_into(comment_saved)
|
||||||
|
|
|
@ -6,7 +6,8 @@ use lemmy_db_schema::{
|
||||||
PersonId,
|
PersonId,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Reportable<CommentReportForm> for CommentReport {
|
impl Reportable for CommentReport {
|
||||||
|
type Form = CommentReportForm;
|
||||||
/// creates a comment report and returns it
|
/// creates a comment report and returns it
|
||||||
///
|
///
|
||||||
/// * `conn` - the postgres connection
|
/// * `conn` - the postgres connection
|
||||||
|
|
|
@ -60,7 +60,9 @@ mod safe_type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<CommunityForm, CommunityId> for Community {
|
impl Crud for Community {
|
||||||
|
type Form = CommunityForm;
|
||||||
|
type IdType = CommunityId;
|
||||||
fn read(conn: &PgConnection, community_id: CommunityId) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, community_id: CommunityId) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::community::dsl::*;
|
use lemmy_db_schema::schema::community::dsl::*;
|
||||||
community.find(community_id).first::<Self>(conn)
|
community.find(community_id).first::<Self>(conn)
|
||||||
|
@ -90,7 +92,8 @@ impl Crud<CommunityForm, CommunityId> for Community {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApubObject<CommunityForm> for Community {
|
impl ApubObject for Community {
|
||||||
|
type Form = CommunityForm;
|
||||||
fn read_from_apub_id(conn: &PgConnection, for_actor_id: &DbUrl) -> Result<Self, Error> {
|
fn read_from_apub_id(conn: &PgConnection, for_actor_id: &DbUrl) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::community::dsl::*;
|
use lemmy_db_schema::schema::community::dsl::*;
|
||||||
community
|
community
|
||||||
|
@ -175,7 +178,8 @@ impl Community_ for Community {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Joinable<CommunityModeratorForm> for CommunityModerator {
|
impl Joinable for CommunityModerator {
|
||||||
|
type Form = CommunityModeratorForm;
|
||||||
fn join(
|
fn join(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_moderator_form: &CommunityModeratorForm,
|
community_moderator_form: &CommunityModeratorForm,
|
||||||
|
@ -252,7 +256,8 @@ impl CommunityModerator_ for CommunityModerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bannable<CommunityPersonBanForm> for CommunityPersonBan {
|
impl Bannable for CommunityPersonBan {
|
||||||
|
type Form = CommunityPersonBanForm;
|
||||||
fn ban(
|
fn ban(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_person_ban_form: &CommunityPersonBanForm,
|
community_person_ban_form: &CommunityPersonBanForm,
|
||||||
|
@ -277,7 +282,8 @@ impl Bannable<CommunityPersonBanForm> for CommunityPersonBan {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Followable<CommunityFollowerForm> for CommunityFollower {
|
impl Followable for CommunityFollower {
|
||||||
|
type Form = CommunityFollowerForm;
|
||||||
fn follow(
|
fn follow(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_follower_form: &CommunityFollowerForm,
|
community_follower_form: &CommunityFollowerForm,
|
||||||
|
|
|
@ -91,7 +91,9 @@ impl LocalUser_ for LocalUser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<LocalUserForm, LocalUserId> for LocalUser {
|
impl Crud for LocalUser {
|
||||||
|
type Form = LocalUserForm;
|
||||||
|
type IdType = LocalUserId;
|
||||||
fn read(conn: &PgConnection, local_user_id: LocalUserId) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, local_user_id: LocalUserId) -> Result<Self, Error> {
|
||||||
local_user.find(local_user_id).first::<Self>(conn)
|
local_user.find(local_user_id).first::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@ use crate::Crud;
|
||||||
use diesel::{dsl::*, result::Error, *};
|
use diesel::{dsl::*, result::Error, *};
|
||||||
use lemmy_db_schema::source::moderator::*;
|
use lemmy_db_schema::source::moderator::*;
|
||||||
|
|
||||||
impl Crud<ModRemovePostForm, i32> for ModRemovePost {
|
impl Crud for ModRemovePost {
|
||||||
|
type Form = ModRemovePostForm;
|
||||||
|
type IdType = i32;
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_remove_post::dsl::*;
|
use lemmy_db_schema::schema::mod_remove_post::dsl::*;
|
||||||
mod_remove_post.find(from_id).first::<Self>(conn)
|
mod_remove_post.find(from_id).first::<Self>(conn)
|
||||||
|
@ -23,7 +25,9 @@ impl Crud<ModRemovePostForm, i32> for ModRemovePost {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<ModLockPostForm, i32> for ModLockPost {
|
impl Crud for ModLockPost {
|
||||||
|
type Form = ModLockPostForm;
|
||||||
|
type IdType = i32;
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_lock_post::dsl::*;
|
use lemmy_db_schema::schema::mod_lock_post::dsl::*;
|
||||||
mod_lock_post.find(from_id).first::<Self>(conn)
|
mod_lock_post.find(from_id).first::<Self>(conn)
|
||||||
|
@ -44,7 +48,9 @@ impl Crud<ModLockPostForm, i32> for ModLockPost {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<ModStickyPostForm, i32> for ModStickyPost {
|
impl Crud for ModStickyPost {
|
||||||
|
type Form = ModStickyPostForm;
|
||||||
|
type IdType = i32;
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_sticky_post::dsl::*;
|
use lemmy_db_schema::schema::mod_sticky_post::dsl::*;
|
||||||
mod_sticky_post.find(from_id).first::<Self>(conn)
|
mod_sticky_post.find(from_id).first::<Self>(conn)
|
||||||
|
@ -65,7 +71,9 @@ impl Crud<ModStickyPostForm, i32> for ModStickyPost {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<ModRemoveCommentForm, i32> for ModRemoveComment {
|
impl Crud for ModRemoveComment {
|
||||||
|
type Form = ModRemoveCommentForm;
|
||||||
|
type IdType = i32;
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_remove_comment::dsl::*;
|
use lemmy_db_schema::schema::mod_remove_comment::dsl::*;
|
||||||
mod_remove_comment.find(from_id).first::<Self>(conn)
|
mod_remove_comment.find(from_id).first::<Self>(conn)
|
||||||
|
@ -86,7 +94,9 @@ impl Crud<ModRemoveCommentForm, i32> for ModRemoveComment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<ModRemoveCommunityForm, i32> for ModRemoveCommunity {
|
impl Crud for ModRemoveCommunity {
|
||||||
|
type Form = ModRemoveCommunityForm;
|
||||||
|
type IdType = i32;
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_remove_community::dsl::*;
|
use lemmy_db_schema::schema::mod_remove_community::dsl::*;
|
||||||
mod_remove_community.find(from_id).first::<Self>(conn)
|
mod_remove_community.find(from_id).first::<Self>(conn)
|
||||||
|
@ -111,7 +121,9 @@ impl Crud<ModRemoveCommunityForm, i32> for ModRemoveCommunity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<ModBanFromCommunityForm, i32> for ModBanFromCommunity {
|
impl Crud for ModBanFromCommunity {
|
||||||
|
type Form = ModBanFromCommunityForm;
|
||||||
|
type IdType = i32;
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_ban_from_community::dsl::*;
|
use lemmy_db_schema::schema::mod_ban_from_community::dsl::*;
|
||||||
mod_ban_from_community.find(from_id).first::<Self>(conn)
|
mod_ban_from_community.find(from_id).first::<Self>(conn)
|
||||||
|
@ -136,7 +148,9 @@ impl Crud<ModBanFromCommunityForm, i32> for ModBanFromCommunity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<ModBanForm, i32> for ModBan {
|
impl Crud for ModBan {
|
||||||
|
type Form = ModBanForm;
|
||||||
|
type IdType = i32;
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_ban::dsl::*;
|
use lemmy_db_schema::schema::mod_ban::dsl::*;
|
||||||
mod_ban.find(from_id).first::<Self>(conn)
|
mod_ban.find(from_id).first::<Self>(conn)
|
||||||
|
@ -155,7 +169,9 @@ impl Crud<ModBanForm, i32> for ModBan {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<ModAddCommunityForm, i32> for ModAddCommunity {
|
impl Crud for ModAddCommunity {
|
||||||
|
type Form = ModAddCommunityForm;
|
||||||
|
type IdType = i32;
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_add_community::dsl::*;
|
use lemmy_db_schema::schema::mod_add_community::dsl::*;
|
||||||
mod_add_community.find(from_id).first::<Self>(conn)
|
mod_add_community.find(from_id).first::<Self>(conn)
|
||||||
|
@ -176,7 +192,9 @@ impl Crud<ModAddCommunityForm, i32> for ModAddCommunity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<ModAddForm, i32> for ModAdd {
|
impl Crud for ModAdd {
|
||||||
|
type Form = ModAddForm;
|
||||||
|
type IdType = i32;
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_add::dsl::*;
|
use lemmy_db_schema::schema::mod_add::dsl::*;
|
||||||
mod_add.find(from_id).first::<Self>(conn)
|
mod_add.find(from_id).first::<Self>(conn)
|
||||||
|
|
|
@ -7,7 +7,9 @@ use lemmy_db_schema::{
|
||||||
};
|
};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
impl Crud<PasswordResetRequestForm, i32> for PasswordResetRequest {
|
impl Crud for PasswordResetRequest {
|
||||||
|
type Form = PasswordResetRequestForm;
|
||||||
|
type IdType = i32;
|
||||||
fn read(conn: &PgConnection, password_reset_request_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, password_reset_request_id: i32) -> Result<Self, Error> {
|
||||||
password_reset_request
|
password_reset_request
|
||||||
.find(password_reset_request_id)
|
.find(password_reset_request_id)
|
||||||
|
|
|
@ -158,7 +158,9 @@ mod safe_type_alias_2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<PersonForm, PersonId> for Person {
|
impl Crud for Person {
|
||||||
|
type Form = PersonForm;
|
||||||
|
type IdType = PersonId;
|
||||||
fn read(conn: &PgConnection, person_id: PersonId) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, person_id: PersonId) -> Result<Self, Error> {
|
||||||
person
|
person
|
||||||
.filter(deleted.eq(false))
|
.filter(deleted.eq(false))
|
||||||
|
@ -178,7 +180,8 @@ impl Crud<PersonForm, PersonId> for Person {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApubObject<PersonForm> for Person {
|
impl ApubObject for Person {
|
||||||
|
type Form = PersonForm;
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error> {
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::person::dsl::*;
|
use lemmy_db_schema::schema::person::dsl::*;
|
||||||
person
|
person
|
||||||
|
|
|
@ -2,7 +2,9 @@ use crate::Crud;
|
||||||
use diesel::{dsl::*, result::Error, *};
|
use diesel::{dsl::*, result::Error, *};
|
||||||
use lemmy_db_schema::{source::person_mention::*, PersonId, PersonMentionId};
|
use lemmy_db_schema::{source::person_mention::*, PersonId, PersonMentionId};
|
||||||
|
|
||||||
impl Crud<PersonMentionForm, PersonMentionId> for PersonMention {
|
impl Crud for PersonMention {
|
||||||
|
type Form = PersonMentionForm;
|
||||||
|
type IdType = PersonMentionId;
|
||||||
fn read(conn: &PgConnection, person_mention_id: PersonMentionId) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, person_mention_id: PersonMentionId) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::person_mention::dsl::*;
|
use lemmy_db_schema::schema::person_mention::dsl::*;
|
||||||
person_mention.find(person_mention_id).first::<Self>(conn)
|
person_mention.find(person_mention_id).first::<Self>(conn)
|
||||||
|
|
|
@ -18,7 +18,9 @@ use lemmy_db_schema::{
|
||||||
PostId,
|
PostId,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Crud<PostForm, PostId> for Post {
|
impl Crud for Post {
|
||||||
|
type Form = PostForm;
|
||||||
|
type IdType = PostId;
|
||||||
fn read(conn: &PgConnection, post_id: PostId) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, post_id: PostId) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::post::dsl::*;
|
use lemmy_db_schema::schema::post::dsl::*;
|
||||||
post.find(post_id).first::<Self>(conn)
|
post.find(post_id).first::<Self>(conn)
|
||||||
|
@ -179,7 +181,8 @@ impl Post_ for Post {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApubObject<PostForm> for Post {
|
impl ApubObject for Post {
|
||||||
|
type Form = PostForm;
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error> {
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::post::dsl::*;
|
use lemmy_db_schema::schema::post::dsl::*;
|
||||||
post.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
post.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
||||||
|
@ -196,7 +199,9 @@ impl ApubObject<PostForm> for Post {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Likeable<PostLikeForm, PostId> for PostLike {
|
impl Likeable for PostLike {
|
||||||
|
type Form = PostLikeForm;
|
||||||
|
type IdType = PostId;
|
||||||
fn like(conn: &PgConnection, post_like_form: &PostLikeForm) -> Result<Self, Error> {
|
fn like(conn: &PgConnection, post_like_form: &PostLikeForm) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::post_like::dsl::*;
|
use lemmy_db_schema::schema::post_like::dsl::*;
|
||||||
insert_into(post_like)
|
insert_into(post_like)
|
||||||
|
@ -217,7 +222,8 @@ impl Likeable<PostLikeForm, PostId> for PostLike {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Saveable<PostSavedForm> for PostSaved {
|
impl Saveable for PostSaved {
|
||||||
|
type Form = PostSavedForm;
|
||||||
fn save(conn: &PgConnection, post_saved_form: &PostSavedForm) -> Result<Self, Error> {
|
fn save(conn: &PgConnection, post_saved_form: &PostSavedForm) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::post_saved::dsl::*;
|
use lemmy_db_schema::schema::post_saved::dsl::*;
|
||||||
insert_into(post_saved)
|
insert_into(post_saved)
|
||||||
|
@ -238,7 +244,8 @@ impl Saveable<PostSavedForm> for PostSaved {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Readable<PostReadForm> for PostRead {
|
impl Readable for PostRead {
|
||||||
|
type Form = PostReadForm;
|
||||||
fn mark_as_read(conn: &PgConnection, post_read_form: &PostReadForm) -> Result<Self, Error> {
|
fn mark_as_read(conn: &PgConnection, post_read_form: &PostReadForm) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::post_read::dsl::*;
|
use lemmy_db_schema::schema::post_read::dsl::*;
|
||||||
insert_into(post_read)
|
insert_into(post_read)
|
||||||
|
|
|
@ -2,7 +2,8 @@ use crate::Reportable;
|
||||||
use diesel::{dsl::*, result::Error, *};
|
use diesel::{dsl::*, result::Error, *};
|
||||||
use lemmy_db_schema::{naive_now, source::post_report::*, PersonId};
|
use lemmy_db_schema::{naive_now, source::post_report::*, PersonId};
|
||||||
|
|
||||||
impl Reportable<PostReportForm> for PostReport {
|
impl Reportable for PostReport {
|
||||||
|
type Form = PostReportForm;
|
||||||
/// creates a post report and returns it
|
/// creates a post report and returns it
|
||||||
///
|
///
|
||||||
/// * `conn` - the postgres connection
|
/// * `conn` - the postgres connection
|
||||||
|
|
|
@ -2,7 +2,9 @@ use crate::{ApubObject, Crud, DeleteableOrRemoveable};
|
||||||
use diesel::{dsl::*, result::Error, *};
|
use diesel::{dsl::*, result::Error, *};
|
||||||
use lemmy_db_schema::{naive_now, source::private_message::*, DbUrl, PersonId, PrivateMessageId};
|
use lemmy_db_schema::{naive_now, source::private_message::*, DbUrl, PersonId, PrivateMessageId};
|
||||||
|
|
||||||
impl Crud<PrivateMessageForm, PrivateMessageId> for PrivateMessage {
|
impl Crud for PrivateMessage {
|
||||||
|
type Form = PrivateMessageForm;
|
||||||
|
type IdType = PrivateMessageId;
|
||||||
fn read(conn: &PgConnection, private_message_id: PrivateMessageId) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, private_message_id: PrivateMessageId) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::private_message::dsl::*;
|
use lemmy_db_schema::schema::private_message::dsl::*;
|
||||||
private_message.find(private_message_id).first::<Self>(conn)
|
private_message.find(private_message_id).first::<Self>(conn)
|
||||||
|
@ -27,7 +29,8 @@ impl Crud<PrivateMessageForm, PrivateMessageId> for PrivateMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApubObject<PrivateMessageForm> for PrivateMessage {
|
impl ApubObject for PrivateMessage {
|
||||||
|
type Form = PrivateMessageForm;
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error>
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
|
|
|
@ -2,7 +2,9 @@ use crate::Crud;
|
||||||
use diesel::{dsl::*, result::Error, *};
|
use diesel::{dsl::*, result::Error, *};
|
||||||
use lemmy_db_schema::{naive_now, source::site::*, PersonId};
|
use lemmy_db_schema::{naive_now, source::site::*, PersonId};
|
||||||
|
|
||||||
impl Crud<SiteForm, i32> for Site {
|
impl Crud for Site {
|
||||||
|
type Form = SiteForm;
|
||||||
|
type IdType = i32;
|
||||||
fn read(conn: &PgConnection, _site_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, _site_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::site::dsl::*;
|
use lemmy_db_schema::schema::site::dsl::*;
|
||||||
site.first::<Self>(conn)
|
site.first::<Self>(conn)
|
||||||
|
|
|
@ -15,6 +15,8 @@ lemmy_utils = { version = "=0.11.3", path = "../utils" }
|
||||||
lemmy_api_common = { version = "=0.11.3", path = "../api_common" }
|
lemmy_api_common = { version = "=0.11.3", path = "../api_common" }
|
||||||
lemmy_db_queries = { version = "=0.11.3", path = "../db_queries" }
|
lemmy_db_queries = { version = "=0.11.3", path = "../db_queries" }
|
||||||
lemmy_db_schema = { version = "=0.11.3", path = "../db_schema" }
|
lemmy_db_schema = { version = "=0.11.3", path = "../db_schema" }
|
||||||
|
lemmy_db_views = { version = "=0.11.3", path = "../db_views" }
|
||||||
|
lemmy_db_views_actor = { version = "=0.11.3", path = "../db_views_actor" }
|
||||||
reqwest = { version = "0.11.4", features = ["json"] }
|
reqwest = { version = "0.11.4", features = ["json"] }
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
rand = "0.8.4"
|
rand = "0.8.4"
|
||||||
|
|
|
@ -13,6 +13,7 @@ pub mod chat_server;
|
||||||
pub mod handlers;
|
pub mod handlers;
|
||||||
pub mod messages;
|
pub mod messages;
|
||||||
pub mod routes;
|
pub mod routes;
|
||||||
|
pub mod send;
|
||||||
|
|
||||||
pub struct LemmyContext {
|
pub struct LemmyContext {
|
||||||
pub pool: DbPool,
|
pub pool: DbPool,
|
||||||
|
|
|
@ -75,7 +75,7 @@ pub struct SendModRoomMessage<Response> {
|
||||||
|
|
||||||
#[derive(Message)]
|
#[derive(Message)]
|
||||||
#[rtype(result = "()")]
|
#[rtype(result = "()")]
|
||||||
pub struct SendPost<OP: ToString> {
|
pub(crate) struct SendPost<OP: ToString> {
|
||||||
pub op: OP,
|
pub op: OP,
|
||||||
pub post: PostResponse,
|
pub post: PostResponse,
|
||||||
pub websocket_id: Option<ConnectionId>,
|
pub websocket_id: Option<ConnectionId>,
|
||||||
|
@ -83,7 +83,7 @@ pub struct SendPost<OP: ToString> {
|
||||||
|
|
||||||
#[derive(Message)]
|
#[derive(Message)]
|
||||||
#[rtype(result = "()")]
|
#[rtype(result = "()")]
|
||||||
pub struct SendComment<OP: ToString> {
|
pub(crate) struct SendComment<OP: ToString> {
|
||||||
pub op: OP,
|
pub op: OP,
|
||||||
pub comment: CommentResponse,
|
pub comment: CommentResponse,
|
||||||
pub websocket_id: Option<ConnectionId>,
|
pub websocket_id: Option<ConnectionId>,
|
||||||
|
|
162
crates/websocket/src/send.rs
Normal file
162
crates/websocket/src/send.rs
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
use crate::{
|
||||||
|
messages::{SendComment, SendCommunityRoomMessage, SendPost, SendUserRoomMessage},
|
||||||
|
LemmyContext,
|
||||||
|
OperationType,
|
||||||
|
};
|
||||||
|
use lemmy_api_common::{
|
||||||
|
blocking,
|
||||||
|
comment::CommentResponse,
|
||||||
|
community::CommunityResponse,
|
||||||
|
person::PrivateMessageResponse,
|
||||||
|
post::PostResponse,
|
||||||
|
};
|
||||||
|
use lemmy_db_queries::DeleteableOrRemoveable;
|
||||||
|
use lemmy_db_schema::{CommentId, CommunityId, LocalUserId, PersonId, PostId, PrivateMessageId};
|
||||||
|
use lemmy_db_views::{
|
||||||
|
comment_view::CommentView,
|
||||||
|
local_user_view::LocalUserView,
|
||||||
|
post_view::PostView,
|
||||||
|
private_message_view::PrivateMessageView,
|
||||||
|
};
|
||||||
|
use lemmy_db_views_actor::community_view::CommunityView;
|
||||||
|
use lemmy_utils::{ConnectionId, LemmyError};
|
||||||
|
|
||||||
|
pub async fn send_post_ws_message<OP: ToString + Send + OperationType + 'static>(
|
||||||
|
post_id: PostId,
|
||||||
|
op: OP,
|
||||||
|
websocket_id: Option<ConnectionId>,
|
||||||
|
person_id: Option<PersonId>,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<PostResponse, LemmyError> {
|
||||||
|
let mut post_view = blocking(context.pool(), move |conn| {
|
||||||
|
PostView::read(conn, post_id, person_id)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
|
||||||
|
if post_view.post.deleted || post_view.post.removed {
|
||||||
|
post_view.post = post_view.post.blank_out_deleted_or_removed_info();
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = PostResponse { post_view };
|
||||||
|
|
||||||
|
context.chat_server().do_send(SendPost {
|
||||||
|
op,
|
||||||
|
post: res.clone(),
|
||||||
|
websocket_id,
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: in many call sites in apub crate, we are setting an empty vec for recipient_ids,
|
||||||
|
// we should get the actual recipient actors from somewhere
|
||||||
|
pub async fn send_comment_ws_message_simple<OP: ToString + Send + OperationType + 'static>(
|
||||||
|
comment_id: CommentId,
|
||||||
|
op: OP,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<CommentResponse, LemmyError> {
|
||||||
|
send_comment_ws_message(comment_id, op, None, None, None, vec![], context).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_comment_ws_message<OP: ToString + Send + OperationType + 'static>(
|
||||||
|
comment_id: CommentId,
|
||||||
|
op: OP,
|
||||||
|
websocket_id: Option<ConnectionId>,
|
||||||
|
form_id: Option<String>,
|
||||||
|
person_id: Option<PersonId>,
|
||||||
|
recipient_ids: Vec<LocalUserId>,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<CommentResponse, LemmyError> {
|
||||||
|
let mut view = blocking(context.pool(), move |conn| {
|
||||||
|
CommentView::read(conn, comment_id, person_id)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
|
||||||
|
if view.comment.deleted || view.comment.removed {
|
||||||
|
view.comment = view.comment.blank_out_deleted_or_removed_info();
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = CommentResponse {
|
||||||
|
comment_view: view,
|
||||||
|
recipient_ids,
|
||||||
|
form_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
context.chat_server().do_send(SendComment {
|
||||||
|
op,
|
||||||
|
comment: res.clone(),
|
||||||
|
websocket_id,
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_community_ws_message<OP: ToString + Send + OperationType + 'static>(
|
||||||
|
community_id: CommunityId,
|
||||||
|
op: OP,
|
||||||
|
websocket_id: Option<ConnectionId>,
|
||||||
|
person_id: Option<PersonId>,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<CommunityResponse, LemmyError> {
|
||||||
|
let mut community_view = blocking(context.pool(), move |conn| {
|
||||||
|
CommunityView::read(conn, community_id, person_id)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
// 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 res = CommunityResponse { community_view };
|
||||||
|
|
||||||
|
// Strip out the person id and subscribed when sending to others
|
||||||
|
let mut res_mut = res.clone();
|
||||||
|
res_mut.community_view.subscribed = false;
|
||||||
|
|
||||||
|
context.chat_server().do_send(SendCommunityRoomMessage {
|
||||||
|
op,
|
||||||
|
response: res_mut,
|
||||||
|
community_id: res.community_view.community.id,
|
||||||
|
websocket_id,
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_pm_ws_message<OP: ToString + Send + OperationType + 'static>(
|
||||||
|
private_message_id: PrivateMessageId,
|
||||||
|
op: OP,
|
||||||
|
websocket_id: Option<ConnectionId>,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<PrivateMessageResponse, LemmyError> {
|
||||||
|
let mut view = blocking(context.pool(), move |conn| {
|
||||||
|
PrivateMessageView::read(conn, 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 res = PrivateMessageResponse {
|
||||||
|
private_message_view: view,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Send notifications to the local recipient, if one exists
|
||||||
|
if res.private_message_view.recipient.local {
|
||||||
|
let recipient_id = res.private_message_view.recipient.id;
|
||||||
|
let local_recipient = blocking(context.pool(), move |conn| {
|
||||||
|
LocalUserView::read_person(conn, recipient_id)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
context.chat_server().do_send(SendUserRoomMessage {
|
||||||
|
op,
|
||||||
|
response: res.clone(),
|
||||||
|
local_recipient_id: local_recipient.local_user.id,
|
||||||
|
websocket_id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
Loading…
Reference in a new issue