From 8a1af056e2a833db88976ad7144deddca74758c0 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 13 Aug 2021 13:39:56 -0400 Subject: [PATCH 1/9] When banning a user, remove communities they've created (#1700) - Fixes #1659 --- crates/api/src/local_user.rs | 21 +++++++++++++++++- .../src/community_moderator_view.rs | 22 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/crates/api/src/local_user.rs b/crates/api/src/local_user.rs index 54fe6d76b..8eee3c1c4 100644 --- a/crates/api/src/local_user.rs +++ b/crates/api/src/local_user.rs @@ -19,6 +19,7 @@ use lemmy_db_queries::{ from_opt_str_to_opt_enum, source::{ comment::Comment_, + community::Community_, local_user::LocalUser_, password_reset_request::PasswordResetRequest_, person::Person_, @@ -33,6 +34,7 @@ use lemmy_db_schema::{ naive_now, source::{ comment::Comment, + community::Community, local_user::{LocalUser, LocalUserForm}, moderator::*, password_reset_request::*, @@ -51,6 +53,7 @@ use lemmy_db_views::{ }; use lemmy_db_views_actor::{ community_follower_view::CommunityFollowerView, + community_moderator_view::CommunityModeratorView, person_mention_view::{PersonMentionQueryBuilder, PersonMentionView}, person_view::PersonViewSafe, }; @@ -408,8 +411,24 @@ impl Perform for BanPerson { // Communities // Remove all communities where they're the top mod - // TODO couldn't get group by's working in diesel, // for now, remove the communities manually + let first_mod_communities = blocking(context.pool(), move |conn: &'_ _| { + CommunityModeratorView::get_community_first_mods(conn) + }) + .await??; + + // Filter to only this banned users top communities + let banned_user_first_communities: Vec = first_mod_communities + .into_iter() + .filter(|fmc| fmc.moderator.id == banned_person_id) + .collect(); + + for first_mod_community in banned_user_first_communities { + blocking(context.pool(), move |conn: &'_ _| { + Community::update_removed(conn, first_mod_community.community.id, true) + }) + .await??; + } // Comments blocking(context.pool(), move |conn: &'_ _| { diff --git a/crates/db_views_actor/src/community_moderator_view.rs b/crates/db_views_actor/src/community_moderator_view.rs index 274f68243..9ea107935 100644 --- a/crates/db_views_actor/src/community_moderator_view.rs +++ b/crates/db_views_actor/src/community_moderator_view.rs @@ -49,6 +49,28 @@ impl CommunityModeratorView { Ok(Self::from_tuple_to_vec(res)) } + + /// Finds all communities first mods / creators + /// Ideally this should be a group by, but diesel doesn't support it yet + pub fn get_community_first_mods(conn: &PgConnection) -> Result, Error> { + let res = community_moderator::table + .inner_join(community::table) + .inner_join(person::table) + .select(( + Community::safe_columns_tuple(), + Person::safe_columns_tuple(), + )) + // A hacky workaround instead of group_bys + // https://stackoverflow.com/questions/24042359/how-to-join-only-one-row-in-joined-table-with-postgres + .distinct_on(community_moderator::community_id) + .order_by(( + community_moderator::community_id, + community_moderator::person_id, + )) + .load::(conn)?; + + Ok(Self::from_tuple_to_vec(res)) + } } impl ViewToVec for CommunityModeratorView { From fb66b77d6704e3d691c5eb16fed3d4ead05f4c3c Mon Sep 17 00:00:00 2001 From: Marcin Wojnarowski Date: Sun, 15 Aug 2021 22:37:37 +0200 Subject: [PATCH 2/9] Update lemmy_api_client status --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ec35ea5cb..0a08c61ce 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ Each Lemmy server can set its own moderation policy; appointing site-wide admins - [lemmy-js-client](https://github.com/LemmyNet/lemmy-js-client) - [Kotlin API ( under development )](https://github.com/eiknat/lemmy-client) -- [Dart API client ( under development )](https://github.com/krawieck/lemmy_api_client) +- [Dart API client](https://github.com/krawieck/lemmy_api_client) ## Support / Donate From 2966203653c16013281af5bc1e6260e73fff4571 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Mon, 16 Aug 2021 16:51:08 -0400 Subject: [PATCH 3/9] Don't allow deleted users to do actions. Fixes #1656 (#1704) --- crates/api_common/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/api_common/src/lib.rs b/crates/api_common/src/lib.rs index 4e3cd751b..1f62a8f3e 100644 --- a/crates/api_common/src/lib.rs +++ b/crates/api_common/src/lib.rs @@ -272,6 +272,11 @@ pub async fn get_local_user_view_from_jwt( return Err(ApiError::err("site_ban").into()); } + // Check for user deletion + if local_user_view.person.deleted { + return Err(ApiError::err("deleted").into()); + } + check_validator_time(&local_user_view.local_user.validator_time, &claims)?; Ok(local_user_view) From 6fbf6a684c383327aa687e49696c7fc327295e88 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Mon, 16 Aug 2021 16:52:24 -0400 Subject: [PATCH 4/9] Make sure bots aren't included in aggregate counts (#1705) - Fixes #1648 --- .../down.sql | 42 +++++++++++++++ .../up.sql | 52 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 migrations/2021-08-16-004209_fix_remove_bots_from_aggregates/down.sql create mode 100644 migrations/2021-08-16-004209_fix_remove_bots_from_aggregates/up.sql diff --git a/migrations/2021-08-16-004209_fix_remove_bots_from_aggregates/down.sql b/migrations/2021-08-16-004209_fix_remove_bots_from_aggregates/down.sql new file mode 100644 index 000000000..a0ec4bdd4 --- /dev/null +++ b/migrations/2021-08-16-004209_fix_remove_bots_from_aggregates/down.sql @@ -0,0 +1,42 @@ +create or replace function community_aggregates_activity(i text) +returns table(count_ bigint, community_id_ integer) +language plpgsql +as +$$ +begin + return query + select count(*), community_id + from ( + select c.creator_id, p.community_id from comment c + inner join post p on c.post_id = p.id + where c.published > ('now'::timestamp - i::interval) + union + select p.creator_id, p.community_id from post p + where p.published > ('now'::timestamp - i::interval) + ) a + group by community_id; +end; +$$; + +create or replace function site_aggregates_activity(i text) returns integer + language plpgsql + as $$ +declare + count_ integer; +begin + select count(*) + into count_ + from ( + select c.creator_id from comment c + inner join person u on c.creator_id = u.id + where c.published > ('now'::timestamp - i::interval) + and u.local = true + union + select p.creator_id from post p + inner join person u on p.creator_id = u.id + where p.published > ('now'::timestamp - i::interval) + and u.local = true + ) a; + return count_; +end; +$$; diff --git a/migrations/2021-08-16-004209_fix_remove_bots_from_aggregates/up.sql b/migrations/2021-08-16-004209_fix_remove_bots_from_aggregates/up.sql new file mode 100644 index 000000000..2aafc3693 --- /dev/null +++ b/migrations/2021-08-16-004209_fix_remove_bots_from_aggregates/up.sql @@ -0,0 +1,52 @@ +-- Make sure bots aren't included in aggregate counts + +create or replace function community_aggregates_activity(i text) +returns table(count_ bigint, community_id_ integer) +language plpgsql +as +$$ +begin + return query + select count(*), community_id + from ( + select c.creator_id, p.community_id from comment c + inner join post p on c.post_id = p.id + inner join person pe on c.creator_id = pe.id + where c.published > ('now'::timestamp - i::interval) + and pe.bot_account = false + union + select p.creator_id, p.community_id from post p + inner join person pe on p.creator_id = pe.id + where p.published > ('now'::timestamp - i::interval) + and pe.bot_account = false + ) a + group by community_id; +end; +$$; + +create or replace function site_aggregates_activity(i text) returns integer + language plpgsql + as $$ +declare + count_ integer; +begin + select count(*) + into count_ + from ( + select c.creator_id from comment c + inner join person u on c.creator_id = u.id + inner join person pe on c.creator_id = pe.id + where c.published > ('now'::timestamp - i::interval) + and u.local = true + and pe.bot_account = false + union + select p.creator_id from post p + inner join person u on p.creator_id = u.id + inner join person pe on p.creator_id = pe.id + where p.published > ('now'::timestamp - i::interval) + and u.local = true + and pe.bot_account = false + ) a; + return count_; +end; +$$; From 28d6370c359d368882d9337d1b32ec2c14987a08 Mon Sep 17 00:00:00 2001 From: Nutomic Date: Tue, 17 Aug 2021 18:04:58 +0000 Subject: [PATCH 5/9] 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 --- Cargo.lock | 2 + crates/api/src/comment.rs | 31 +- crates/api/src/post.rs | 69 ++--- crates/api/src/private_message.rs | 32 +-- crates/api_crud/src/comment/create.rs | 37 +-- crates/api_crud/src/comment/delete.rs | 136 ++++----- crates/api_crud/src/comment/update.rs | 37 +-- crates/api_crud/src/community/delete.rs | 104 +++---- crates/api_crud/src/community/mod.rs | 23 -- crates/api_crud/src/community/update.rs | 35 +-- crates/api_crud/src/post/create.rs | 26 +- crates/api_crud/src/post/delete.rs | 100 +++---- crates/api_crud/src/post/update.rs | 31 +- crates/api_crud/src/private_message/create.rs | 41 ++- crates/api_crud/src/private_message/delete.rs | 39 +-- crates/api_crud/src/private_message/update.rs | 41 +-- .../activities/comment/create_or_update.rs | 10 +- crates/apub/src/activities/comment/mod.rs | 37 +-- .../apub/src/activities/community/announce.rs | 16 +- crates/apub/src/activities/community/mod.rs | 30 +- .../apub/src/activities/community/update.rs | 16 +- crates/apub/src/activities/deletion/delete.rs | 269 +++++++++++------- crates/apub/src/activities/deletion/mod.rs | 207 ++++++++++++++ .../src/activities/deletion/undo_delete.rs | 201 +++++++------ .../src/activities/post/create_or_update.rs | 6 +- crates/apub/src/activities/post/mod.rs | 29 -- .../private_message/create_or_update.rs | 12 +- .../src/activities/private_message/delete.rs | 12 +- .../src/activities/private_message/mod.rs | 38 --- .../activities/private_message/undo_delete.rs | 7 +- crates/apub/src/activities/removal/remove.rs | 112 ++------ .../src/activities/removal/undo_remove.rs | 100 ++----- crates/apub/src/activities/send/comment.rs | 153 ---------- crates/apub/src/activities/send/community.rs | 118 +------- crates/apub/src/activities/send/mod.rs | 2 - crates/apub/src/activities/send/post.rs | 139 --------- crates/apub/src/activities/voting/mod.rs | 37 +-- crates/apub/src/extensions/context.rs | 2 +- crates/apub/src/extensions/signatures.rs | 2 +- crates/apub/src/fetcher/community.rs | 2 +- crates/apub/src/fetcher/mod.rs | 2 +- crates/apub/src/fetcher/objects.rs | 6 +- crates/apub/src/fetcher/person.rs | 2 +- crates/apub/src/http/inbox_enums.rs | 19 +- crates/apub/src/lib.rs | 43 +-- crates/apub/src/migrations.rs | 12 + crates/apub/src/objects/mod.rs | 4 +- crates/db_queries/src/lib.rs | 69 +++-- crates/db_queries/src/source/activity.rs | 4 +- crates/db_queries/src/source/comment.rs | 14 +- .../db_queries/src/source/comment_report.rs | 3 +- crates/db_queries/src/source/community.rs | 16 +- crates/db_queries/src/source/local_user.rs | 4 +- crates/db_queries/src/source/moderator.rs | 36 ++- .../src/source/password_reset_request.rs | 4 +- crates/db_queries/src/source/person.rs | 7 +- .../db_queries/src/source/person_mention.rs | 4 +- crates/db_queries/src/source/post.rs | 17 +- crates/db_queries/src/source/post_report.rs | 3 +- .../db_queries/src/source/private_message.rs | 7 +- crates/db_queries/src/source/site.rs | 4 +- crates/websocket/Cargo.toml | 2 + crates/websocket/src/lib.rs | 1 + crates/websocket/src/messages.rs | 4 +- crates/websocket/src/send.rs | 162 +++++++++++ 65 files changed, 1170 insertions(+), 1620 deletions(-) delete mode 100644 crates/apub/src/activities/send/comment.rs delete mode 100644 crates/apub/src/activities/send/post.rs create mode 100644 crates/websocket/src/send.rs diff --git a/Cargo.lock b/Cargo.lock index 34431d3ad..844d49e10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1944,6 +1944,8 @@ dependencies = [ "lemmy_api_common", "lemmy_db_queries", "lemmy_db_schema", + "lemmy_db_views", + "lemmy_db_views_actor", "lemmy_utils", "log", "rand 0.8.4", diff --git a/crates/api/src/comment.rs b/crates/api/src/comment.rs index f92e679f7..06510251f 100644 --- a/crates/api/src/comment.rs +++ b/crates/api/src/comment.rs @@ -18,7 +18,7 @@ use lemmy_db_queries::{source::comment::Comment_, Likeable, Saveable}; use lemmy_db_schema::{source::comment::*, LocalUserId}; use lemmy_db_views::{comment_view::CommentView, local_user_view::LocalUserView}; 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; #[async_trait::async_trait(?Send)] @@ -206,26 +206,15 @@ impl Perform for CreateCommentLike { .await?; } - // Have to refetch the comment to get the current state - let comment_id = data.comment_id; - let person_id = local_user_view.person.id; - 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(), + send_comment_ws_message( + data.comment_id, + UserOperation::CreateCommentLike, websocket_id, - }); - - Ok(res) + None, + Some(local_user_view.person.id), + recipient_ids, + context, + ) + .await } } diff --git a/crates/api/src/post.rs b/crates/api/src/post.rs index 684f64798..3de027313 100644 --- a/crates/api/src/post.rs +++ b/crates/api/src/post.rs @@ -24,7 +24,7 @@ use lemmy_db_queries::{source::post::Post_, Crud, Likeable, Saveable}; use lemmy_db_schema::source::{moderator::*, post::*}; use lemmy_db_views::post_view::PostView; 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; #[async_trait::async_trait(?Send)] @@ -96,23 +96,14 @@ impl Perform for CreatePostLike { // Mark the post as read mark_post_as_read(person_id, post_id, context.pool()).await?; - let post_id = data.post_id; - let person_id = local_user_view.person.id; - let post_view = blocking(context.pool(), move |conn| { - 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(), + send_post_ws_message( + data.post_id, + UserOperation::CreatePostLike, websocket_id, - }); - - Ok(res) + Some(local_user_view.person.id), + context, + ) + .await } } @@ -171,22 +162,14 @@ impl Perform for LockPost { ) .await?; - // Refetch the post - let post_id = data.post_id; - let post_view = blocking(context.pool(), move |conn| { - 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(), + send_post_ws_message( + data.post_id, + UserOperation::LockPost, websocket_id, - }); - - Ok(res) + Some(local_user_view.person.id), + context, + ) + .await } } @@ -249,22 +232,14 @@ impl Perform for StickyPost { ) .await?; - // Refetch the post - let post_id = data.post_id; - let post_view = blocking(context.pool(), move |conn| { - 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(), + send_post_ws_message( + data.post_id, + UserOperation::StickyPost, websocket_id, - }); - - Ok(res) + Some(local_user_view.person.id), + context, + ) + .await } } diff --git a/crates/api/src/private_message.rs b/crates/api/src/private_message.rs index 54bc3eb0c..f23bf71cd 100644 --- a/crates/api/src/private_message.rs +++ b/crates/api/src/private_message.rs @@ -7,9 +7,8 @@ use lemmy_api_common::{ }; use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud}; 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_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperation}; +use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperation}; #[async_trait::async_trait(?Send)] impl Perform for MarkPrivateMessageAsRead { @@ -43,32 +42,7 @@ impl Perform for MarkPrivateMessageAsRead { .map_err(|_| ApiError::err("couldnt_update_private_message"))?; // No need to send an apub update - let private_message_id = data.private_message_id; - let private_message_view = blocking(context.pool(), move |conn| { - 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) + let op = UserOperation::MarkPrivateMessageAsRead; + send_pm_ws_message(data.private_message_id, op, websocket_id, context).await } } diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs index 5a6fec81c..a479969a7 100644 --- a/crates/api_crud/src/comment/create.rs +++ b/crates/api_crud/src/comment/create.rs @@ -20,14 +20,13 @@ use lemmy_apub::{ }; use lemmy_db_queries::{source::comment::Comment_, Crud, Likeable}; use lemmy_db_schema::source::comment::*; -use lemmy_db_views::comment_view::CommentView; use lemmy_utils::{ utils::{remove_slurs, scrape_text_for_mentions}, 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)] impl PerformCrud for CreateComment { @@ -137,37 +136,25 @@ impl PerformCrud for CreateComment { ) .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 - let comment_id = comment_view.comment.id; - if local_user_view.person.id == comment_view.get_recipient_id() { + if local_user_view.person.id == inserted_comment.creator_id { + let comment_id = inserted_comment.id; blocking(context.pool(), move |conn| { Comment::update_read(conn, comment_id, true) }) .await? .map_err(|_| ApiError::err("couldnt_update_comment"))?; - comment_view.comment.read = true; } - let mut res = CommentResponse { - comment_view, - recipient_ids, - form_id: data.form_id.to_owned(), - }; - - context.chat_server().do_send(SendComment { - op: UserOperationCrud::CreateComment, - comment: res.clone(), + send_comment_ws_message( + inserted_comment.id, + UserOperationCrud::CreateComment, websocket_id, - }); - - res.recipient_ids = Vec::new(); // Necessary to avoid doubles - - Ok(res) + data.form_id.to_owned(), + Some(local_user_view.person.id), + recipient_ids, + context, + ) + .await } } diff --git a/crates/api_crud/src/comment/delete.rs b/crates/api_crud/src/comment/delete.rs index e2ec3080e..85917846e 100644 --- a/crates/api_crud/src/comment/delete.rs +++ b/crates/api_crud/src/comment/delete.rs @@ -8,12 +8,12 @@ use lemmy_api_common::{ is_mod_or_admin, send_local_notifs, }; -use lemmy_apub::ApubObjectType; -use lemmy_db_queries::{source::comment::Comment_, Crud, DeleteableOrRemoveable}; -use lemmy_db_schema::source::{comment::*, moderator::*}; +use lemmy_apub::activities::deletion::{send_apub_delete, send_apub_remove}; +use lemmy_db_queries::{source::comment::Comment_, Crud}; +use lemmy_db_schema::source::{comment::*, community::Community, moderator::*, post::Post}; use lemmy_db_views::comment_view::CommentView; 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)] impl PerformCrud for DeleteComment { @@ -47,63 +47,48 @@ impl PerformCrud for DeleteComment { // Do the delete 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) }) .await? .map_err(|_| ApiError::err("couldnt_update_comment"))?; // Send the apub message - if deleted { - updated_comment = updated_comment.blank_out_deleted_or_removed_info(); - 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)) + let community = blocking(context.pool(), move |conn| { + Community::read(conn, orig_comment.post.community_id) }) .await??; + send_apub_delete( + &local_user_view.person, + &community, + updated_comment.ap_id.clone().into(), + deleted, + context, + ) + .await?; - // Blank out deleted or removed info - if deleted { - 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 post_id = updated_comment.post_id; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let recipient_ids = send_local_notifs( - mentions, + vec![], updated_comment, local_user_view.person.clone(), - comment_view_2.post, + post, context.pool(), false, ) .await?; - let res = CommentResponse { - comment_view, - recipient_ids, - form_id: None, // TODO a comment delete might clear forms? - }; - - context.chat_server().do_send(SendComment { - op: UserOperationCrud::DeleteComment, - comment: res.clone(), + send_comment_ws_message( + data.comment_id, + UserOperationCrud::DeleteComment, websocket_id, - }); - - Ok(res) + None, // TODO a comment delete might clear forms? + Some(local_user_view.person.id), + recipient_ids, + context, + ) + .await } } @@ -142,7 +127,7 @@ impl PerformCrud for RemoveComment { // Do the remove 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) }) .await? @@ -161,56 +146,41 @@ impl PerformCrud for RemoveComment { .await??; // Send the apub message - if removed { - updated_comment = updated_comment.blank_out_deleted_or_removed_info(); - 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)) + let community = blocking(context.pool(), move |conn| { + Community::read(conn, orig_comment.post.community_id) }) .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 - if removed { - 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 post_id = updated_comment.post_id; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let recipient_ids = send_local_notifs( - mentions, + vec![], updated_comment, local_user_view.person.clone(), - comment_view_2.post, + post, context.pool(), false, ) .await?; - let res = CommentResponse { - comment_view, - recipient_ids, - form_id: None, // TODO maybe this might clear other forms - }; - - context.chat_server().do_send(SendComment { - op: UserOperationCrud::RemoveComment, - comment: res.clone(), + send_comment_ws_message( + data.comment_id, + UserOperationCrud::RemoveComment, websocket_id, - }); - - Ok(res) + None, // TODO maybe this might clear other forms + Some(local_user_view.person.id), + recipient_ids, + context, + ) + .await } } diff --git a/crates/api_crud/src/comment/update.rs b/crates/api_crud/src/comment/update.rs index d0a0e3971..ee2e7e28e 100644 --- a/crates/api_crud/src/comment/update.rs +++ b/crates/api_crud/src/comment/update.rs @@ -11,7 +11,7 @@ use lemmy_apub::activities::{ comment::create_or_update::CreateOrUpdateComment, 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_views::comment_view::CommentView; use lemmy_utils::{ @@ -20,7 +20,7 @@ use lemmy_utils::{ ConnectionId, LemmyError, }; -use lemmy_websocket::{messages::SendComment, LemmyContext, UserOperationCrud}; +use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud}; #[async_trait::async_trait(?Send)] impl PerformCrud for EditComment { @@ -83,30 +83,15 @@ impl PerformCrud for EditComment { ) .await?; - 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??; - - // 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(), + send_comment_ws_message( + data.comment_id, + UserOperationCrud::EditComment, websocket_id, - }); - - Ok(res) + data.form_id.to_owned(), + None, + recipient_ids, + context, + ) + .await } } diff --git a/crates/api_crud/src/community/delete.rs b/crates/api_crud/src/community/delete.rs index 62fb0f38f..b957b7d6e 100644 --- a/crates/api_crud/src/community/delete.rs +++ b/crates/api_crud/src/community/delete.rs @@ -1,18 +1,15 @@ -use crate::{community::send_community_websocket, PerformCrud}; +use crate::PerformCrud; use actix_web::web::Data; use lemmy_api_common::{blocking, community::*, get_local_user_view_from_jwt, is_admin}; -use lemmy_apub::CommunityType; -use lemmy_db_queries::{source::community::Community_, Crud, DeleteableOrRemoveable}; +use lemmy_apub::activities::deletion::{send_apub_delete, send_apub_remove}; +use lemmy_db_queries::{source::community::Community_, Crud}; use lemmy_db_schema::source::{ community::*, moderator::{ModRemoveCommunity, ModRemoveCommunityForm}, }; -use lemmy_db_views_actor::{ - community_moderator_view::CommunityModeratorView, - community_view::CommunityView, -}; +use lemmy_db_views_actor::community_moderator_view::CommunityModeratorView; 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)] impl PerformCrud for DeleteCommunity { @@ -48,39 +45,23 @@ impl PerformCrud for DeleteCommunity { .map_err(|_| ApiError::err("couldnt_update_community"))?; // Send apub messages - if deleted { - updated_community - .blank_out_deleted_or_removed_info() - .send_delete(local_user_view.person.to_owned(), context) - .await?; - } 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, + send_apub_delete( + &local_user_view.person, + &updated_community, + updated_community.actor_id.clone().into(), + deleted, 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??; // Apub messages - if removed { - updated_community - .blank_out_deleted_or_removed_info() - .send_remove(context) - .await?; - } else { - 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, + send_apub_remove( + &local_user_view.person, + &updated_community, + updated_community.actor_id.clone().into(), + data.reason.clone().unwrap_or_else(|| "".to_string()), + removed, 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 } } diff --git a/crates/api_crud/src/community/mod.rs b/crates/api_crud/src/community/mod.rs index 9098cb541..716832376 100644 --- a/crates/api_crud/src/community/mod.rs +++ b/crates/api_crud/src/community/mod.rs @@ -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 delete; mod read; mod update; - -pub(in crate::community) fn send_community_websocket( - res: &CommunityResponse, - context: &Data, - websocket_id: Option, - 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, - }); -} diff --git a/crates/api_crud/src/community/update.rs b/crates/api_crud/src/community/update.rs index 49de1cfd7..2a99c76db 100644 --- a/crates/api_crud/src/community/update.rs +++ b/crates/api_crud/src/community/update.rs @@ -1,4 +1,4 @@ -use crate::{community::send_community_websocket, PerformCrud}; +use crate::PerformCrud; use actix_web::web::Data; use lemmy_api_common::{ blocking, @@ -6,18 +6,15 @@ use lemmy_api_common::{ get_local_user_view_from_jwt, }; 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::{ naive_now, source::community::{Community, CommunityForm}, PersonId, }; -use lemmy_db_views_actor::{ - community_moderator_view::CommunityModeratorView, - community_view::CommunityView, -}; +use lemmy_db_views_actor::community_moderator_view::CommunityModeratorView; 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)] impl PerformCrud for EditCommunity { @@ -76,27 +73,7 @@ impl PerformCrud for EditCommunity { .send_update(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 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) + let op = UserOperationCrud::EditCommunity; + send_community_ws_message(data.community_id, op, websocket_id, None, context).await } } diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index f041a00b1..28c739689 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -19,7 +19,6 @@ use lemmy_apub::{ }; use lemmy_db_queries::{source::post::Post_, Crud, Likeable}; use lemmy_db_schema::source::post::*; -use lemmy_db_views::post_view::PostView; use lemmy_utils::{ request::fetch_iframely_and_pictrs_data, utils::{check_slurs, check_slurs_opt, clean_url_params, is_valid_post_title}, @@ -27,7 +26,7 @@ use lemmy_utils::{ ConnectionId, LemmyError, }; -use lemmy_websocket::{messages::SendPost, LemmyContext, UserOperationCrud}; +use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud}; #[async_trait::async_trait(?Send)] impl PerformCrud for CreatePost { @@ -129,22 +128,13 @@ impl PerformCrud for CreatePost { ) .await?; - // Refetch the view - let inserted_post_id = inserted_post.id; - let post_view = blocking(context.pool(), move |conn| { - 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(), + send_post_ws_message( + inserted_post.id, + UserOperationCrud::CreatePost, websocket_id, - }); - - Ok(res) + Some(local_user_view.person.id), + context, + ) + .await } } diff --git a/crates/api_crud/src/post/delete.rs b/crates/api_crud/src/post/delete.rs index cf48757d3..c0ef35122 100644 --- a/crates/api_crud/src/post/delete.rs +++ b/crates/api_crud/src/post/delete.rs @@ -7,12 +7,11 @@ use lemmy_api_common::{ is_mod_or_admin, post::*, }; -use lemmy_apub::ApubObjectType; -use lemmy_db_queries::{source::post::Post_, Crud, DeleteableOrRemoveable}; -use lemmy_db_schema::source::{moderator::*, post::*}; -use lemmy_db_views::post_view::PostView; +use lemmy_apub::activities::deletion::{send_apub_delete, send_apub_remove}; +use lemmy_db_queries::{source::post::Post_, Crud}; +use lemmy_db_schema::source::{community::Community, moderator::*, post::*}; 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)] impl PerformCrud for DeletePost { @@ -50,37 +49,27 @@ impl PerformCrud for DeletePost { .await??; // apub updates - if deleted { - updated_post - .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)) + let community = blocking(context.pool(), move |conn| { + Community::read(conn, orig_post.community_id) }) .await??; + send_apub_delete( + &local_user_view.person, + &community, + updated_post.ap_id.into(), + deleted, + context, + ) + .await?; - if deleted { - 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::DeletePost, - post: res.clone(), + send_post_ws_message( + data.post_id, + UserOperationCrud::DeletePost, websocket_id, - }); - - Ok(res) + Some(local_user_view.person.id), + context, + ) + .await } } @@ -135,38 +124,27 @@ impl PerformCrud for RemovePost { .await??; // apub updates - if removed { - updated_post - .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)) + let community = blocking(context.pool(), move |conn| { + Community::read(conn, orig_post.community_id) }) .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 - if 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::RemovePost, - post: res.clone(), + send_post_ws_message( + data.post_id, + UserOperationCrud::RemovePost, websocket_id, - }); - - Ok(res) + Some(local_user_view.person.id), + context, + ) + .await } } diff --git a/crates/api_crud/src/post/update.rs b/crates/api_crud/src/post/update.rs index c9fe7e332..4b63ebd2c 100644 --- a/crates/api_crud/src/post/update.rs +++ b/crates/api_crud/src/post/update.rs @@ -2,9 +2,8 @@ use crate::PerformCrud; use actix_web::web::Data; 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_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_views::post_view::PostView; use lemmy_utils::{ request::fetch_iframely_and_pictrs_data, utils::{check_slurs_opt, clean_url_params, is_valid_post_title}, @@ -12,7 +11,7 @@ use lemmy_utils::{ ConnectionId, LemmyError, }; -use lemmy_websocket::{messages::SendPost, LemmyContext, UserOperationCrud}; +use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud}; #[async_trait::async_trait(?Send)] impl PerformCrud for EditPost { @@ -100,25 +99,13 @@ impl PerformCrud for EditPost { ) .await?; - 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??; - - // 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(), + send_post_ws_message( + data.post_id, + UserOperationCrud::EditPost, websocket_id, - }); - - Ok(res) + Some(local_user_view.person.id), + context, + ) + .await } } diff --git a/crates/api_crud/src/private_message/create.rs b/crates/api_crud/src/private_message/create.rs index 1da6466df..aa0bc8f4c 100644 --- a/crates/api_crud/src/private_message/create.rs +++ b/crates/api_crud/src/private_message/create.rs @@ -16,9 +16,9 @@ use lemmy_apub::{ }; use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud}; 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_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperationCrud}; +use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud}; #[async_trait::async_trait(?Send)] impl PerformCrud for CreatePrivateMessage { @@ -78,36 +78,27 @@ impl PerformCrud for CreatePrivateMessage { ) .await?; - let private_message_view = blocking(context.pool(), move |conn| { - PrivateMessageView::read(conn, inserted_private_message.id) - }) - .await??; + let res = send_pm_ws_message( + inserted_private_message.id, + UserOperationCrud::CreatePrivateMessage, + websocket_id, + context, + ) + .await?; - let res = PrivateMessageResponse { - private_message_view, - }; - - // Send notifications to the local recipient, if one exists - let recipient_id = data.recipient_id; - if let Ok(local_recipient) = blocking(context.pool(), move |conn| { - LocalUserView::read_person(conn, recipient_id) - }) - .await? - { + // Send email to the local recipient, if one exists + if res.private_message_view.recipient.local { + let recipient_id = data.recipient_id; + let local_recipient = blocking(context.pool(), move |conn| { + LocalUserView::read_person(conn, recipient_id) + }) + .await??; send_email_to_user( &local_recipient, "Private Message from", "Private Message", &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) diff --git a/crates/api_crud/src/private_message/delete.rs b/crates/api_crud/src/private_message/delete.rs index 78dcd9311..6cd2b44f2 100644 --- a/crates/api_crud/src/private_message/delete.rs +++ b/crates/api_crud/src/private_message/delete.rs @@ -11,9 +11,8 @@ use lemmy_apub::activities::private_message::{ }; use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud, DeleteableOrRemoveable}; 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_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperationCrud}; +use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud}; #[async_trait::async_trait(?Send)] impl PerformCrud for DeletePrivateMessage { @@ -59,39 +58,7 @@ impl PerformCrud for DeletePrivateMessage { .await?; } - let private_message_id = data.private_message_id; - let mut private_message_view = blocking(context.pool(), move |conn| { - 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) + let op = UserOperationCrud::DeletePrivateMessage; + send_pm_ws_message(data.private_message_id, op, websocket_id, context).await } } diff --git a/crates/api_crud/src/private_message/update.rs b/crates/api_crud/src/private_message/update.rs index 5f5f7b845..72ca4fbbf 100644 --- a/crates/api_crud/src/private_message/update.rs +++ b/crates/api_crud/src/private_message/update.rs @@ -9,11 +9,10 @@ use lemmy_apub::activities::{ private_message::create_or_update::CreateOrUpdatePrivateMessage, 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_views::{local_user_view::LocalUserView, private_message_view::PrivateMessageView}; 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)] impl PerformCrud for EditPrivateMessage { @@ -55,39 +54,7 @@ impl PerformCrud for EditPrivateMessage { ) .await?; - let private_message_id = data.private_message_id; - let mut private_message_view = blocking(context.pool(), move |conn| { - 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) + let op = UserOperationCrud::EditPrivateMessage; + send_pm_ws_message(data.private_message_id, op, websocket_id, context).await } } diff --git a/crates/apub/src/activities/comment/create_or_update.rs b/crates/apub/src/activities/comment/create_or_update.rs index bfc1b7fe6..cb9b23497 100644 --- a/crates/apub/src/activities/comment/create_or_update.rs +++ b/crates/apub/src/activities/comment/create_or_update.rs @@ -1,6 +1,6 @@ use crate::{ activities::{ - comment::{collect_non_local_mentions, get_notif_recipients, send_websocket_message}, + comment::{collect_non_local_mentions, get_notif_recipients}, community::announce::AnnouncableActivities, extract_community, generate_activity_id, @@ -24,7 +24,7 @@ use lemmy_apub_lib::{ 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, UserOperationCrud}; +use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud}; use serde::{Deserialize, Serialize}; use url::Url; @@ -116,7 +116,11 @@ impl ActivityHandler for CreateOrUpdateComment { CreateOrUpdateType::Create => UserOperationCrud::CreateComment, 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 { diff --git a/crates/apub/src/activities/comment/mod.rs b/crates/apub/src/activities/comment/mod.rs index e7499718c..228a5f804 100644 --- a/crates/apub/src/activities/comment/mod.rs +++ b/crates/apub/src/activities/comment/mod.rs @@ -5,21 +5,19 @@ use activitystreams::{ }; use anyhow::anyhow; 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_schema::{ source::{comment::Comment, community::Community, person::Person, post::Post}, - CommentId, LocalUserId, }; -use lemmy_db_views::comment_view::CommentView; use lemmy_utils::{ request::{retry, RecvError}, settings::structs::Settings, utils::{scrape_text_for_mentions, MentionData}, LemmyError, }; -use lemmy_websocket::{messages::SendComment, LemmyContext}; +use lemmy_websocket::LemmyContext; use log::debug; use reqwest::Client; use url::Url; @@ -45,37 +43,6 @@ async fn get_notif_recipients( 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, - 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 ccs: Vec, pub inboxes: Vec, diff --git a/crates/apub/src/activities/community/announce.rs b/crates/apub/src/activities/community/announce.rs index fc3bebfed..734fed00e 100644 --- a/crates/apub/src/activities/community/announce.rs +++ b/crates/apub/src/activities/community/announce.rs @@ -7,16 +7,10 @@ use crate::{ list_community_follower_inboxes, undo_block_user::UndoBlockUserFromCommunity, }, - deletion::{ - delete::DeletePostCommentOrCommunity, - undo_delete::UndoDeletePostCommentOrCommunity, - }, + deletion::{delete::Delete, undo_delete::UndoDelete}, generate_activity_id, post::create_or_update::CreateOrUpdatePost, - removal::{ - remove::RemovePostCommentCommunityOrMod, - undo_remove::UndoRemovePostCommentOrCommunity, - }, + removal::{remove::RemoveMod, undo_remove::UndoRemovePostCommentOrCommunity}, verify_activity, verify_community, voting::{undo_vote::UndoVote, vote::Vote}, @@ -43,13 +37,13 @@ pub enum AnnouncableActivities { CreateOrUpdatePost(Box), Vote(Vote), UndoVote(UndoVote), - DeletePostCommentOrCommunity(DeletePostCommentOrCommunity), - UndoDeletePostCommentOrCommunity(UndoDeletePostCommentOrCommunity), - RemovePostCommentCommunityOrMod(RemovePostCommentCommunityOrMod), + Delete(Delete), + UndoDelete(UndoDelete), UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity), BlockUserFromCommunity(BlockUserFromCommunity), UndoBlockUserFromCommunity(UndoBlockUserFromCommunity), AddMod(AddMod), + RemoveMod(RemoveMod), } #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] diff --git a/crates/apub/src/activities/community/mod.rs b/crates/apub/src/activities/community/mod.rs index 4151471ad..49cf9615f 100644 --- a/crates/apub/src/activities/community/mod.rs +++ b/crates/apub/src/activities/community/mod.rs @@ -1,10 +1,8 @@ use crate::{check_is_apub_id_valid, CommunityType}; use itertools::Itertools; -use lemmy_api_common::{blocking, community::CommunityResponse}; -use lemmy_db_schema::{source::community::Community, CommunityId}; -use lemmy_db_views_actor::community_view::CommunityView; +use lemmy_db_schema::source::community::Community; use lemmy_utils::{settings::structs::Settings, LemmyError}; -use lemmy_websocket::{messages::SendCommunityRoomMessage, LemmyContext}; +use lemmy_websocket::LemmyContext; use url::Url; pub mod add_mod; @@ -13,30 +11,6 @@ pub mod block_user; pub mod undo_block_user; 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( community: &Community, additional_inboxes: Vec, diff --git a/crates/apub/src/activities/community/update.rs b/crates/apub/src/activities/community/update.rs index 964a42388..d38d722bf 100644 --- a/crates/apub/src/activities/community/update.rs +++ b/crates/apub/src/activities/community/update.rs @@ -1,10 +1,5 @@ use crate::{ - activities::{ - community::send_websocket_message, - verify_activity, - verify_mod_action, - verify_person_in_community, - }, + activities::{verify_activity, verify_mod_action, verify_person_in_community}, objects::community::Group, }; 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_schema::source::community::{Community, CommunityForm}; use lemmy_utils::LemmyError; -use lemmy_websocket::{LemmyContext, UserOperationCrud}; +use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud}; use url::Url; /// This activity is received from a remote community mod, and updates the description or other @@ -71,12 +66,15 @@ impl ActivityHandler for UpdateCommunity { }) .await??; - send_websocket_message( + send_community_ws_message( updated_community.id, UserOperationCrud::EditCommunity, + None, + None, context, ) - .await + .await?; + Ok(()) } fn common(&self) -> &ActivityCommonFields { diff --git a/crates/apub/src/activities/deletion/delete.rs b/crates/apub/src/activities/deletion/delete.rs index d377a6696..093919b88 100644 --- a/crates/apub/src/activities/deletion/delete.rs +++ b/crates/apub/src/activities/deletion/delete.rs @@ -1,31 +1,48 @@ use crate::{ activities::{ - comment::send_websocket_message as send_comment_message, - community::send_websocket_message as send_community_message, - post::send_websocket_message as send_post_message, + community::announce::AnnouncableActivities, + deletion::{ + receive_delete_action, + verify_delete_activity, + DeletableObjects, + WebsocketMessages, + }, + generate_activity_id, 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, - CommunityType, - PostOrComment, }; use activitystreams::activity::kind::DeleteType; +use anyhow::anyhow; 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_}, 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_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; /// 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. #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] -pub struct DeletePostCommentOrCommunity { - to: PublicUrl, +pub struct Delete { + pub(in crate::activities::deletion) to: PublicUrl, pub(in crate::activities::deletion) object: Url, - cc: [Url; 1], + pub(in crate::activities::deletion) cc: [Url; 1], #[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, #[serde(flatten)] - common: ActivityCommonFields, + pub(in crate::activities::deletion) common: ActivityCommonFields, } #[async_trait::async_trait(?Send)] -impl ActivityHandler for DeletePostCommentOrCommunity { +impl ActivityHandler for Delete { async fn verify( &self, context: &LemmyContext, request_counter: &mut i32, ) -> Result<(), LemmyError> { verify_activity(self.common())?; - let object_community = - get_or_fetch_and_upsert_community(&self.object, context, request_counter).await; - // deleting a community (set counter 0 to only fetch from local db) - if object_community.is_ok() { - verify_mod_action(&self.common.actor, self.object.clone(), context).await?; - } - // deleting a post or comment - else { - verify_person_in_community(&self.common().actor, &self.cc[0], context, request_counter) - .await?; - let object_creator = - get_post_or_comment_actor_id(&self.object, context, request_counter).await?; - verify_urls_match(&self.common.actor, &object_creator)?; - } + verify_delete_activity( + &self.object, + &self.cc[0], + &self.common, + self.summary.is_some(), + context, + request_counter, + ) + .await?; Ok(()) } @@ -78,55 +93,36 @@ impl ActivityHandler for DeletePostCommentOrCommunity { context: &LemmyContext, request_counter: &mut i32, ) -> Result<(), LemmyError> { - let object_community = - get_or_fetch_and_upsert_community(&self.object, context, request_counter).await; - // deleting a community - if let Ok(community) = object_community { - if community.local { - // repeat these checks just to be sure - verify_person_in_community(&self.common().actor, &self.cc[0], context, request_counter) - .await?; - verify_mod_action(&self.common.actor, self.object.clone(), context).await?; - let mod_ = - get_or_fetch_and_upsert_person(&self.common.actor, context, request_counter).await?; - community.send_delete(mod_, context).await?; - } - let deleted_community = blocking(context.pool(), move |conn| { - Community::update_deleted(conn, community.id, true) - }) - .await??; - - send_community_message( - deleted_community.id, - UserOperationCrud::DeleteCommunity, + if let Some(reason) = self.summary { + // We set reason to empty string if it doesn't exist, to distinguish between delete and + // remove. Here we change it back to option, so we don't write it to db. + let reason = if reason.is_empty() { + None + } else { + Some(reason) + }; + receive_remove_action( + &self.common.actor, + &self.object, + reason, context, + request_counter, + ) + .await + } else { + receive_delete_action( + &self.object, + &self.common.actor, + WebsocketMessages { + community: UserOperationCrud::DeleteCommunity, + post: UserOperationCrud::DeletePost, + comment: UserOperationCrud::DeleteComment, + }, + true, + context, + request_counter, ) .await - } - // deleting a post or comment - else { - match get_or_fetch_and_insert_post_or_comment(&self.object, context, request_counter).await? { - PostOrComment::Post(post) => { - let deleted_post = blocking(context.pool(), move |conn| { - Post::update_deleted(conn, post.id, true) - }) - .await??; - send_post_message(deleted_post.id, UserOperationCrud::EditPost, context).await - } - PostOrComment::Comment(comment) => { - let deleted_comment = blocking(context.pool(), move |conn| { - Comment::update_deleted(conn, comment.id, true) - }) - .await??; - send_comment_message( - deleted_comment.id, - vec![], - UserOperationCrud::EditComment, - context, - ) - .await - } - } } } @@ -135,25 +131,102 @@ impl ActivityHandler for DeletePostCommentOrCommunity { } } -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, + 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, + reason: Option, context: &LemmyContext, request_counter: &mut i32, -) -> Result { - let actor_id = - match get_or_fetch_and_insert_post_or_comment(object, context, request_counter).await? { - PostOrComment::Post(post) => { - let creator_id = post.creator_id; - blocking(context.pool(), move |conn| Person::read(conn, creator_id)) - .await?? - .actor_id() +) -> Result<(), LemmyError> { + let actor = get_or_fetch_and_upsert_person(actor, context, request_counter).await?; + use UserOperationCrud::*; + match DeletableObjects::read_from_db(object, context).await? { + DeletableObjects::Community(community) => { + if community.local { + return Err(anyhow!("Only local admin can remove community").into()); } - PostOrComment::Comment(comment) => { - let creator_id = comment.creator_id; - blocking(context.pool(), move |conn| Person::read(conn, creator_id)) - .await?? - .actor_id() - } - }; - Ok(actor_id) + let form = ModRemoveCommunityForm { + mod_person_id: actor.id, + community_id: community.id, + removed: Some(true), + reason, + expires: None, + }; + 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(()) } diff --git a/crates/apub/src/activities/deletion/mod.rs b/crates/apub/src/activities/deletion/mod.rs index b440edd68..cf73be097 100644 --- a/crates/apub/src/activities/deletion/mod.rs +++ b/crates/apub/src/activities/deletion/mod.rs @@ -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 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), + Comment(Box), + Post(Box), +} + +impl DeletableObjects { + pub(crate) async fn read_from_db( + ap_id: &Url, + context: &LemmyContext, + ) -> Result { + let id: DbUrl = ap_id.clone().into(); + + if let Some(c) = DeletableObjects::read_type_from_db::(id.clone(), context).await? { + return Ok(DeletableObjects::Community(Box::new(c))); + } + if let Some(p) = DeletableObjects::read_type_from_db::(id.clone(), context).await? { + return Ok(DeletableObjects::Post(Box::new(p))); + } + if let Some(c) = DeletableObjects::read_type_from_db::(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( + ap_id: DbUrl, + context: &LemmyContext, + ) -> Result, 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(()) +} diff --git a/crates/apub/src/activities/deletion/undo_delete.rs b/crates/apub/src/activities/deletion/undo_delete.rs index e57e6b401..0114acac8 100644 --- a/crates/apub/src/activities/deletion/undo_delete.rs +++ b/crates/apub/src/activities/deletion/undo_delete.rs @@ -1,35 +1,39 @@ use crate::{ activities::{ - comment::send_websocket_message as send_comment_message, - community::send_websocket_message as send_community_message, - deletion::delete::DeletePostCommentOrCommunity, - post::send_websocket_message as send_post_message, + community::announce::AnnouncableActivities, + deletion::{ + delete::Delete, + receive_delete_action, + verify_delete_activity, + DeletableObjects, + WebsocketMessages, + }, + generate_activity_id, 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, - }, - CommunityType, - PostOrComment, + activity_queue::send_to_community_new, + extensions::context::lemmy_context, + ActorType, }; -use activitystreams::activity::kind::UndoType; +use activitystreams::activity::kind::{DeleteType, UndoType}; +use anyhow::anyhow; use lemmy_api_common::blocking; -use lemmy_apub_lib::{values::PublicUrl, verify_urls_match, ActivityCommonFields, ActivityHandler}; +use lemmy_apub_lib::{values::PublicUrl, ActivityCommonFields, ActivityHandler}; use lemmy_db_queries::source::{comment::Comment_, community::Community_, post::Post_}; -use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post}; +use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post}; 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; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] -pub struct UndoDeletePostCommentOrCommunity { +pub struct UndoDelete { to: PublicUrl, - object: DeletePostCommentOrCommunity, + object: Delete, cc: [Url; 1], #[serde(rename = "type")] kind: UndoType, @@ -38,7 +42,7 @@ pub struct UndoDeletePostCommentOrCommunity { } #[async_trait::async_trait(?Send)] -impl ActivityHandler for UndoDeletePostCommentOrCommunity { +impl ActivityHandler for UndoDelete { async fn verify( &self, context: &LemmyContext, @@ -46,18 +50,15 @@ impl ActivityHandler for UndoDeletePostCommentOrCommunity { ) -> Result<(), LemmyError> { verify_activity(self.common())?; self.object.verify(context, request_counter).await?; - let object_community = - get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await; - // restoring a community - if object_community.is_ok() { - verify_mod_action(&self.common.actor, self.object.object.clone(), context).await?; - } - // restoring a post or comment - else { - verify_person_in_community(&self.common().actor, &self.cc[0], context, request_counter) - .await?; - verify_urls_match(&self.common.actor, &self.object.common().actor)?; - } + verify_delete_activity( + &self.object.object, + &self.cc[0], + &self.common, + self.object.summary.is_some(), + context, + request_counter, + ) + .await?; Ok(()) } @@ -66,61 +67,101 @@ impl ActivityHandler for UndoDeletePostCommentOrCommunity { context: &LemmyContext, request_counter: &mut i32, ) -> Result<(), LemmyError> { - let object_community = - get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await; - // restoring a community - if let Ok(community) = object_community { - if community.local { - // repeat these checks just to be sure - verify_person_in_community(&self.common().actor, &self.cc[0], context, request_counter) - .await?; - verify_mod_action(&self.common.actor, self.object.object.clone(), context).await?; - let mod_ = - get_or_fetch_and_upsert_person(&self.common.actor, context, request_counter).await?; - community.send_undo_delete(mod_, context).await?; - } - let deleted_community = blocking(context.pool(), move |conn| { - Community::update_deleted(conn, community.id, false) - }) - .await??; - - send_community_message( - deleted_community.id, - UserOperationCrud::EditCommunity, + if self.object.summary.is_some() { + UndoDelete::receive_undo_remove_action(&self.object.object, context).await + } else { + receive_delete_action( + &self.object.object, + &self.common.actor, + WebsocketMessages { + community: UserOperationCrud::EditCommunity, + post: UserOperationCrud::EditPost, + comment: UserOperationCrud::EditComment, + }, + false, context, + request_counter, ) .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 { &self.common } } + +impl UndoDelete { + pub(in crate::activities::deletion) async fn send( + actor: &Person, + community: &Community, + object_id: Url, + summary: Option, + 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(()) + } +} diff --git a/crates/apub/src/activities/post/create_or_update.rs b/crates/apub/src/activities/post/create_or_update.rs index 94838e16f..1a9c77689 100644 --- a/crates/apub/src/activities/post/create_or_update.rs +++ b/crates/apub/src/activities/post/create_or_update.rs @@ -3,7 +3,6 @@ use crate::{ community::announce::AnnouncableActivities, extract_community, generate_activity_id, - post::send_websocket_message, verify_activity, verify_mod_action, verify_person_in_community, @@ -27,7 +26,7 @@ use lemmy_apub_lib::{ use lemmy_db_queries::Crud; use lemmy_db_schema::source::{community::Community, person::Person, post::Post}; use lemmy_utils::LemmyError; -use lemmy_websocket::{LemmyContext, UserOperationCrud}; +use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud}; use url::Url; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] @@ -126,7 +125,8 @@ impl ActivityHandler for CreateOrUpdatePost { CreateOrUpdateType::Create => UserOperationCrud::CreatePost, 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 { diff --git a/crates/apub/src/activities/post/mod.rs b/crates/apub/src/activities/post/mod.rs index b60348ed0..e903f52ff 100644 --- a/crates/apub/src/activities/post/mod.rs +++ b/crates/apub/src/activities/post/mod.rs @@ -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(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(()) -} diff --git a/crates/apub/src/activities/private_message/create_or_update.rs b/crates/apub/src/activities/private_message/create_or_update.rs index 09582689b..cd3c65744 100644 --- a/crates/apub/src/activities/private_message/create_or_update.rs +++ b/crates/apub/src/activities/private_message/create_or_update.rs @@ -1,11 +1,5 @@ use crate::{ - activities::{ - generate_activity_id, - private_message::send_websocket_message, - verify_activity, - verify_person, - CreateOrUpdateType, - }, + activities::{generate_activity_id, verify_activity, verify_person, CreateOrUpdateType}, activity_queue::send_activity_new, extensions::context::lemmy_context, 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_schema::source::{person::Person, private_message::PrivateMessage}; use lemmy_utils::LemmyError; -use lemmy_websocket::{LemmyContext, UserOperationCrud}; +use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud}; use url::Url; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] @@ -83,7 +77,7 @@ impl ActivityHandler for CreateOrUpdatePrivateMessage { CreateOrUpdateType::Create => UserOperationCrud::CreatePrivateMessage, 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(()) } diff --git a/crates/apub/src/activities/private_message/delete.rs b/crates/apub/src/activities/private_message/delete.rs index 4c990a2d1..e6c03093b 100644 --- a/crates/apub/src/activities/private_message/delete.rs +++ b/crates/apub/src/activities/private_message/delete.rs @@ -1,10 +1,5 @@ use crate::{ - activities::{ - generate_activity_id, - private_message::send_websocket_message, - verify_activity, - verify_person, - }, + activities::{generate_activity_id, verify_activity, verify_person}, activity_queue::send_activity_new, extensions::context::lemmy_context, 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_schema::source::{person::Person, private_message::PrivateMessage}; use lemmy_utils::LemmyError; -use lemmy_websocket::{LemmyContext, UserOperationCrud}; +use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud}; use url::Url; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] @@ -84,9 +79,10 @@ impl ActivityHandler for DeletePrivateMessage { }) .await??; - send_websocket_message( + send_pm_ws_message( deleted_private_message.id, UserOperationCrud::DeletePrivateMessage, + None, context, ) .await?; diff --git a/crates/apub/src/activities/private_message/mod.rs b/crates/apub/src/activities/private_message/mod.rs index 0c0557286..4bcda7c7b 100644 --- a/crates/apub/src/activities/private_message/mod.rs +++ b/crates/apub/src/activities/private_message/mod.rs @@ -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 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(()) -} diff --git a/crates/apub/src/activities/private_message/undo_delete.rs b/crates/apub/src/activities/private_message/undo_delete.rs index 5bbca90e6..4cd2a139d 100644 --- a/crates/apub/src/activities/private_message/undo_delete.rs +++ b/crates/apub/src/activities/private_message/undo_delete.rs @@ -1,7 +1,7 @@ use crate::{ activities::{ generate_activity_id, - private_message::{delete::DeletePrivateMessage, send_websocket_message}, + private_message::delete::DeletePrivateMessage, verify_activity, verify_person, }, @@ -20,7 +20,7 @@ use lemmy_apub_lib::{ use lemmy_db_queries::{source::private_message::PrivateMessage_, ApubObject, Crud}; use lemmy_db_schema::source::{person::Person, private_message::PrivateMessage}; use lemmy_utils::LemmyError; -use lemmy_websocket::{LemmyContext, UserOperationCrud}; +use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud}; use url::Url; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] @@ -104,9 +104,10 @@ impl ActivityHandler for UndoDeletePrivateMessage { }) .await??; - send_websocket_message( + send_pm_ws_message( deleted_private_message.id, UserOperationCrud::EditPrivateMessage, + None, context, ) .await?; diff --git a/crates/apub/src/activities/removal/remove.rs b/crates/apub/src/activities/removal/remove.rs index 83aaabc6f..1bd6e0a03 100644 --- a/crates/apub/src/activities/removal/remove.rs +++ b/crates/apub/src/activities/removal/remove.rs @@ -1,77 +1,59 @@ use crate::{ activities::{ - comment::send_websocket_message as send_comment_message, - community::send_websocket_message as send_community_message, - post::send_websocket_message as send_post_message, + deletion::{delete::receive_remove_action, verify_delete_activity}, verify_activity, verify_add_remove_moderator_target, verify_mod_action, verify_person_in_community, }, - fetcher::{ - community::get_or_fetch_and_upsert_community, - objects::get_or_fetch_and_insert_post_or_comment, - person::get_or_fetch_and_upsert_person, - }, + fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person}, CommunityType, - PostOrComment, }; use activitystreams::{activity::kind::RemoveType, base::AnyBase}; -use anyhow::anyhow; use lemmy_api_common::blocking; use lemmy_apub_lib::{values::PublicUrl, ActivityCommonFields, ActivityHandler}; -use lemmy_db_queries::{ - source::{comment::Comment_, community::Community_, post::Post_}, - Joinable, -}; -use lemmy_db_schema::source::{ - comment::Comment, - community::{Community, CommunityModerator, CommunityModeratorForm}, - post::Post, -}; +use lemmy_db_queries::Joinable; +use lemmy_db_schema::source::community::{CommunityModerator, CommunityModeratorForm}; use lemmy_utils::LemmyError; -use lemmy_websocket::{LemmyContext, UserOperationCrud}; +use lemmy_websocket::LemmyContext; use url::Url; -// TODO: we can probably deduplicate a bunch of code between this and DeletePostCommentOrCommunity #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] -pub struct RemovePostCommentCommunityOrMod { +pub struct RemoveMod { to: PublicUrl, pub(in crate::activities::removal) object: Url, cc: [Url; 1], #[serde(rename = "type")] kind: RemoveType, // if target is set, this is means remove mod from community - target: Option, + pub(in crate::activities::removal) target: Option, #[serde(flatten)] common: ActivityCommonFields, } #[async_trait::async_trait(?Send)] -impl ActivityHandler for RemovePostCommentCommunityOrMod { +impl ActivityHandler for RemoveMod { async fn verify( &self, context: &LemmyContext, request_counter: &mut i32, ) -> Result<(), LemmyError> { verify_activity(self.common())?; - let object_community = - get_or_fetch_and_upsert_community(&self.object, context, request_counter).await; - // 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 { + if let Some(target) = &self.target { 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_add_remove_moderator_target(target, self.cc[0].clone())?; - } - // 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?; + } else { + verify_delete_activity( + &self.object, + &self.cc[0], + self.common(), + true, + context, + request_counter, + ) + .await?; } Ok(()) } @@ -81,27 +63,7 @@ impl ActivityHandler for RemovePostCommentCommunityOrMod { context: &LemmyContext, request_counter: &mut i32, ) -> Result<(), LemmyError> { - let object_community = - 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() { + if self.target.is_some() { let community = get_or_fetch_and_upsert_community(&self.cc[0], context, request_counter).await?; let remove_mod = @@ -121,31 +83,15 @@ impl ActivityHandler for RemovePostCommentCommunityOrMod { .await?; // TODO: send websocket notification about removed mod Ok(()) - } - // removing a post or comment - else { - match get_or_fetch_and_insert_post_or_comment(&self.object, context, request_counter).await? { - PostOrComment::Post(post) => { - 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, - ) - .await - } - } + } else { + receive_remove_action( + &self.common.actor, + &self.object, + None, + context, + request_counter, + ) + .await } } diff --git a/crates/apub/src/activities/removal/undo_remove.rs b/crates/apub/src/activities/removal/undo_remove.rs index 003eb4aaa..e2c7ef76f 100644 --- a/crates/apub/src/activities/removal/undo_remove.rs +++ b/crates/apub/src/activities/removal/undo_remove.rs @@ -1,34 +1,20 @@ -use crate::{ - activities::{ - comment::send_websocket_message as send_comment_message, - community::send_websocket_message as send_community_message, - post::send_websocket_message as send_post_message, - removal::remove::RemovePostCommentCommunityOrMod, - 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 crate::activities::{ + deletion::{undo_delete::UndoDelete, verify_delete_activity}, + removal::remove::RemoveMod, + verify_activity, }; use activitystreams::activity::kind::UndoType; -use anyhow::anyhow; -use lemmy_api_common::blocking; use lemmy_apub_lib::{values::PublicUrl, ActivityCommonFields, ActivityHandler}; -use lemmy_db_queries::source::{comment::Comment_, community::Community_, post::Post_}; -use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post}; use lemmy_utils::LemmyError; -use lemmy_websocket::{LemmyContext, UserOperationCrud}; +use lemmy_websocket::LemmyContext; use url::Url; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] pub struct UndoRemovePostCommentOrCommunity { to: PublicUrl, - object: RemovePostCommentCommunityOrMod, + // Note, there is no such thing as Undo/Remove/Mod, so we ignore that + object: RemoveMod, cc: [Url; 1], #[serde(rename = "type")] kind: UndoType, @@ -44,74 +30,26 @@ impl ActivityHandler for UndoRemovePostCommentOrCommunity { request_counter: &mut i32, ) -> Result<(), LemmyError> { 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?; - // 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(()) } async fn receive( self, context: &LemmyContext, - request_counter: &mut i32, + _request_counter: &mut i32, ) -> Result<(), LemmyError> { - let object_community = - get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await; - // restoring a community - if let Ok(community) = object_community { - if community.local { - 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 - } - } - } + UndoDelete::receive_undo_remove_action(&self.object.object, context).await } fn common(&self) -> &ActivityCommonFields { diff --git a/crates/apub/src/activities/send/comment.rs b/crates/apub/src/activities/send/comment.rs deleted file mode 100644 index 8b446860a..000000000 --- a/crates/apub/src/activities/send/comment.rs +++ /dev/null @@ -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(()) - } -} diff --git a/crates/apub/src/activities/send/community.rs b/crates/apub/src/activities/send/community.rs index 6f88dd36f..a103f95c6 100644 --- a/crates/apub/src/activities/send/community.rs +++ b/crates/apub/src/activities/send/community.rs @@ -12,20 +12,10 @@ use crate::{ }; use activitystreams::{ activity::{ - kind::{ - AddType, - AnnounceType, - BlockType, - DeleteType, - LikeType, - RemoveType, - UndoType, - UpdateType, - }, + kind::{AddType, AnnounceType, BlockType, RemoveType, UndoType, UpdateType}, Add, Announce, Block, - Delete, OptTargetRefExt, Remove, Undo, @@ -97,112 +87,6 @@ impl CommunityType for Community { 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 /// community followers. /// diff --git a/crates/apub/src/activities/send/mod.rs b/crates/apub/src/activities/send/mod.rs index c00ecb1a7..a01cddd6d 100644 --- a/crates/apub/src/activities/send/mod.rs +++ b/crates/apub/src/activities/send/mod.rs @@ -1,4 +1,2 @@ -pub(crate) mod comment; pub(crate) mod community; pub(crate) mod person; -pub(crate) mod post; diff --git a/crates/apub/src/activities/send/post.rs b/crates/apub/src/activities/send/post.rs deleted file mode 100644 index b9713661b..000000000 --- a/crates/apub/src/activities/send/post.rs +++ /dev/null @@ -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(()) - } -} diff --git a/crates/apub/src/activities/voting/mod.rs b/crates/apub/src/activities/voting/mod.rs index 48d9446f8..48d44c0ee 100644 --- a/crates/apub/src/activities/voting/mod.rs +++ b/crates/apub/src/activities/voting/mod.rs @@ -1,8 +1,4 @@ -use crate::activities::{ - comment::send_websocket_message as send_comment_message, - post::send_websocket_message as send_post_message, - voting::vote::VoteType, -}; +use crate::activities::voting::vote::VoteType; use lemmy_api_common::blocking; use lemmy_db_queries::Likeable; use lemmy_db_schema::source::{ @@ -11,7 +7,11 @@ use lemmy_db_schema::source::{ post::{Post, PostLike, PostLikeForm}, }; 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 vote; @@ -36,13 +36,8 @@ async fn vote_comment( }) .await??; - send_comment_message( - comment_id, - vec![], - UserOperation::CreateCommentLike, - context, - ) - .await + send_comment_ws_message_simple(comment_id, UserOperation::CreateCommentLike, context).await?; + Ok(()) } async fn vote_post( @@ -64,7 +59,8 @@ async fn vote_post( }) .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( @@ -79,13 +75,8 @@ async fn undo_vote_comment( }) .await??; - send_comment_message( - comment.id, - vec![], - UserOperation::CreateCommentLike, - context, - ) - .await + send_comment_ws_message_simple(comment_id, UserOperation::CreateCommentLike, context).await?; + Ok(()) } async fn undo_vote_post( @@ -99,5 +90,7 @@ async fn undo_vote_post( PostLike::remove(conn, person_id, post_id) }) .await??; - send_post_message(post.id, UserOperation::CreatePostLike, context).await + + send_post_ws_message(post_id, UserOperation::CreatePostLike, None, None, context).await?; + Ok(()) } diff --git a/crates/apub/src/extensions/context.rs b/crates/apub/src/extensions/context.rs index 1d6f83bd7..bc58052f0 100644 --- a/crates/apub/src/extensions/context.rs +++ b/crates/apub/src/extensions/context.rs @@ -2,7 +2,7 @@ use activitystreams::{base::AnyBase, context, primitives::OneOrMany}; use serde_json::json; use url::Url; -pub fn lemmy_context() -> OneOrMany { +pub(crate) fn lemmy_context() -> OneOrMany { let context_ext = AnyBase::from_arbitrary_json(json!( { "sc": "http://schema.org#", diff --git a/crates/apub/src/extensions/signatures.rs b/crates/apub/src/extensions/signatures.rs index 8fded5152..675740365 100644 --- a/crates/apub/src/extensions/signatures.rs +++ b/crates/apub/src/extensions/signatures.rs @@ -62,7 +62,7 @@ pub(crate) async fn sign_and_send( } /// 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 .begin_verify( request.method(), diff --git a/crates/apub/src/fetcher/community.rs b/crates/apub/src/fetcher/community.rs index ff94129be..83aa7b51e 100644 --- a/crates/apub/src/fetcher/community.rs +++ b/crates/apub/src/fetcher/community.rs @@ -25,7 +25,7 @@ use url::Url; /// /// 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. -pub async fn get_or_fetch_and_upsert_community( +pub(crate) async fn get_or_fetch_and_upsert_community( apub_id: &Url, context: &LemmyContext, recursion_counter: &mut i32, diff --git a/crates/apub/src/fetcher/mod.rs b/crates/apub/src/fetcher/mod.rs index 477cecc87..9d9e2b8e3 100644 --- a/crates/apub/src/fetcher/mod.rs +++ b/crates/apub/src/fetcher/mod.rs @@ -42,7 +42,7 @@ where /// /// 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. -pub async fn get_or_fetch_and_upsert_actor( +pub(crate) async fn get_or_fetch_and_upsert_actor( apub_id: &Url, context: &LemmyContext, recursion_counter: &mut i32, diff --git a/crates/apub/src/fetcher/objects.rs b/crates/apub/src/fetcher/objects.rs index 835bf63a3..e538982db 100644 --- a/crates/apub/src/fetcher/objects.rs +++ b/crates/apub/src/fetcher/objects.rs @@ -17,7 +17,7 @@ use url::Url; /// pulled from its apub ID, inserted and returned. /// /// 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, context: &LemmyContext, 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. /// /// 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, context: &LemmyContext, 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, context: &LemmyContext, recursion_counter: &mut i32, diff --git a/crates/apub/src/fetcher/person.rs b/crates/apub/src/fetcher/person.rs index 3acedb086..ed3ca057f 100644 --- a/crates/apub/src/fetcher/person.rs +++ b/crates/apub/src/fetcher/person.rs @@ -16,7 +16,7 @@ use url::Url; /// /// 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. -pub async fn get_or_fetch_and_upsert_person( +pub(crate) async fn get_or_fetch_and_upsert_person( apub_id: &Url, context: &LemmyContext, recursion_counter: &mut i32, diff --git a/crates/apub/src/http/inbox_enums.rs b/crates/apub/src/http/inbox_enums.rs index 034048777..1ed210bb5 100644 --- a/crates/apub/src/http/inbox_enums.rs +++ b/crates/apub/src/http/inbox_enums.rs @@ -7,7 +7,7 @@ use crate::activities::{ undo_block_user::UndoBlockUserFromCommunity, update::UpdateCommunity, }, - deletion::{delete::DeletePostCommentOrCommunity, undo_delete::UndoDeletePostCommentOrCommunity}, + deletion::{delete::Delete, undo_delete::UndoDelete}, following::{accept::AcceptFollowCommunity, follow::FollowCommunity, undo::UndoFollowCommunity}, post::create_or_update::CreateOrUpdatePost, private_message::{ @@ -15,10 +15,7 @@ use crate::activities::{ delete::DeletePrivateMessage, undo_delete::UndoDeletePrivateMessage, }, - removal::{ - remove::RemovePostCommentCommunityOrMod, - undo_remove::UndoRemovePostCommentOrCommunity, - }, + removal::{remove::RemoveMod, undo_remove::UndoRemovePostCommentOrCommunity}, voting::{undo_vote::UndoVote, vote::Vote}, }; use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler}; @@ -45,14 +42,14 @@ pub enum GroupInboxActivities { CreateOrUpdatePost(Box), Vote(Vote), UndoVote(UndoVote), - DeletePostCommentOrCommunity(DeletePostCommentOrCommunity), - UndoDeletePostCommentOrCommunity(UndoDeletePostCommentOrCommunity), - RemovePostCommentOrCommunity(RemovePostCommentCommunityOrMod), + DeletePostCommentOrCommunity(Delete), + UndoDeletePostCommentOrCommunity(UndoDelete), UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity), UpdateCommunity(Box), BlockUserFromCommunity(BlockUserFromCommunity), UndoBlockUserFromCommunity(UndoBlockUserFromCommunity), AddMod(AddMod), + RemoveMod(RemoveMod), } #[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)] @@ -65,14 +62,14 @@ pub enum SharedInboxActivities { CreateOrUpdatePost(Box), Vote(Vote), UndoVote(UndoVote), - DeletePostCommentOrCommunity(DeletePostCommentOrCommunity), - UndoDeletePostCommentOrCommunity(UndoDeletePostCommentOrCommunity), - RemovePostCommentOrCommunity(RemovePostCommentCommunityOrMod), + Delete(Delete), + UndoDelete(UndoDelete), UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity), UpdateCommunity(Box), BlockUserFromCommunity(BlockUserFromCommunity), UndoBlockUserFromCommunity(UndoBlockUserFromCommunity), AddMod(AddMod), + RemoveMod(RemoveMod), // received by person AcceptFollowCommunity(AcceptFollowCommunity), // Note, pm activities need to be at the end, otherwise comments will end up here. We can probably diff --git a/crates/apub/src/lib.rs b/crates/apub/src/lib.rs index 950f11dc4..477143009 100644 --- a/crates/apub/src/lib.rs +++ b/crates/apub/src/lib.rs @@ -34,7 +34,7 @@ use serde::Serialize; use std::net::IpAddr; 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. /// @@ -102,28 +102,9 @@ pub(crate) fn check_is_apub_id_valid( 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 /// implemented by all actors. -pub trait ActorType { +trait ActorType { fn is_local(&self) -> bool; fn actor_id(&self) -> Url; fn name(&self) -> String; @@ -160,11 +141,6 @@ pub trait CommunityType { async fn get_follower_inboxes(&self, pool: &DbPool) -> 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( &self, @@ -209,7 +185,7 @@ pub enum EndpointType { } /// 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, name: &str, domain: &str, @@ -260,7 +236,7 @@ pub fn generate_shared_inbox_url(actor_id: &DbUrl) -> Result Ok(Url::parse(&url)?.into()) } -pub fn generate_moderators_url(community_id: &DbUrl) -> Result { +fn generate_moderators_url(community_id: &DbUrl) -> Result { 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 /// persistent. -pub(crate) async fn insert_activity( +async fn insert_activity( ap_id: &Url, activity: T, local: bool, @@ -348,7 +324,7 @@ pub(crate) async fn find_post_or_comment_by_id( } #[derive(Debug)] -pub enum Object { +enum Object { Comment(Box), Post(Box), Community(Box), @@ -356,10 +332,7 @@ pub enum Object { PrivateMessage(Box), } -pub(crate) async fn find_object_by_id( - context: &LemmyContext, - apub_id: Url, -) -> Result { +async fn find_object_by_id(context: &LemmyContext, apub_id: Url) -> Result { let ap_id = apub_id.clone(); if let Ok(pc) = find_post_or_comment_by_id(context, ap_id.to_owned()).await { return Ok(match pc { @@ -397,7 +370,7 @@ pub(crate) async fn find_object_by_id( Err(NotFound.into()) } -pub(crate) async fn check_community_or_site_ban( +async fn check_community_or_site_ban( person: &Person, community_id: CommunityId, pool: &DbPool, diff --git a/crates/apub/src/migrations.rs b/crates/apub/src/migrations.rs index 0f18d2f37..59eeacce9 100644 --- a/crates/apub/src/migrations.rs +++ b/crates/apub/src/migrations.rs @@ -15,3 +15,15 @@ pub enum CommentInReplyToMigration { Old(Vec), 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. diff --git a/crates/apub/src/objects/mod.rs b/crates/apub/src/objects/mod.rs index 2114a1d89..33a93915a 100644 --- a/crates/apub/src/objects/mod.rs +++ b/crates/apub/src/objects/mod.rs @@ -19,14 +19,14 @@ pub(crate) mod private_message; /// Trait for converting an object or actor into the respective ActivityPub type. #[async_trait::async_trait(?Send)] -pub trait ToApub { +pub(crate) trait ToApub { type ApubType; async fn to_apub(&self, pool: &DbPool) -> Result; fn to_tombstone(&self) -> Result; } #[async_trait::async_trait(?Send)] -pub trait FromApub { +pub(crate) trait FromApub { type ApubType; /// Converts an object from ActivityPub type to Lemmy internal type. /// diff --git a/crates/db_queries/src/lib.rs b/crates/db_queries/src/lib.rs index adc0717ac..fb5b8cd5d 100644 --- a/crates/db_queries/src/lib.rs +++ b/crates/db_queries/src/lib.rs @@ -25,17 +25,19 @@ pub mod source; pub type DbPool = diesel::r2d2::Pool>; -pub trait Crud { - fn create(conn: &PgConnection, form: &Form) -> Result +pub trait Crud { + type Form; + type IdType; + fn create(conn: &PgConnection, form: &Self::Form) -> Result where Self: Sized; - fn read(conn: &PgConnection, id: IdType) -> Result + fn read(conn: &PgConnection, id: Self::IdType) -> Result where Self: Sized; - fn update(conn: &PgConnection, id: IdType, form: &Form) -> Result + fn update(conn: &PgConnection, id: Self::IdType, form: &Self::Form) -> Result where Self: Sized; - fn delete(_conn: &PgConnection, _id: IdType) -> Result + fn delete(_conn: &PgConnection, _id: Self::IdType) -> Result where Self: Sized, { @@ -43,8 +45,9 @@ pub trait Crud { } } -pub trait Followable
{ - fn follow(conn: &PgConnection, form: &Form) -> Result +pub trait Followable { + type Form; + fn follow(conn: &PgConnection, form: &Self::Form) -> Result where Self: Sized; fn follow_accepted( @@ -54,59 +57,70 @@ pub trait Followable { ) -> Result where Self: Sized; - fn unfollow(conn: &PgConnection, form: &Form) -> Result + fn unfollow(conn: &PgConnection, form: &Self::Form) -> Result where Self: Sized; fn has_local_followers(conn: &PgConnection, community_id: CommunityId) -> Result; } -pub trait Joinable { - fn join(conn: &PgConnection, form: &Form) -> Result +pub trait Joinable { + type Form; + fn join(conn: &PgConnection, form: &Self::Form) -> Result where Self: Sized; - fn leave(conn: &PgConnection, form: &Form) -> Result + fn leave(conn: &PgConnection, form: &Self::Form) -> Result where Self: Sized; } -pub trait Likeable { - fn like(conn: &PgConnection, form: &Form) -> Result +pub trait Likeable { + type Form; + type IdType; + fn like(conn: &PgConnection, form: &Self::Form) -> Result where Self: Sized; - fn remove(conn: &PgConnection, person_id: PersonId, item_id: IdType) -> Result + fn remove( + conn: &PgConnection, + person_id: PersonId, + item_id: Self::IdType, + ) -> Result where Self: Sized; } -pub trait Bannable { - fn ban(conn: &PgConnection, form: &Form) -> Result +pub trait Bannable { + type Form; + fn ban(conn: &PgConnection, form: &Self::Form) -> Result where Self: Sized; - fn unban(conn: &PgConnection, form: &Form) -> Result + fn unban(conn: &PgConnection, form: &Self::Form) -> Result where Self: Sized; } -pub trait Saveable { - fn save(conn: &PgConnection, form: &Form) -> Result +pub trait Saveable { + type Form; + fn save(conn: &PgConnection, form: &Self::Form) -> Result where Self: Sized; - fn unsave(conn: &PgConnection, form: &Form) -> Result + fn unsave(conn: &PgConnection, form: &Self::Form) -> Result where Self: Sized; } -pub trait Readable { - fn mark_as_read(conn: &PgConnection, form: &Form) -> Result +pub trait Readable { + type Form; + fn mark_as_read(conn: &PgConnection, form: &Self::Form) -> Result where Self: Sized; - fn mark_as_unread(conn: &PgConnection, form: &Form) -> Result + fn mark_as_unread(conn: &PgConnection, form: &Self::Form) -> Result where Self: Sized; } -pub trait Reportable { - fn report(conn: &PgConnection, form: &Form) -> Result +pub trait Reportable { + type Form; + fn report(conn: &PgConnection, form: &Self::Form) -> Result where Self: Sized; fn resolve(conn: &PgConnection, report_id: i32, resolver_id: PersonId) -> Result @@ -121,11 +135,12 @@ pub trait DeleteableOrRemoveable { fn blank_out_deleted_or_removed_info(self) -> Self; } -pub trait ApubObject { +pub trait ApubObject { + type Form; fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result where Self: Sized; - fn upsert(conn: &PgConnection, user_form: &Form) -> Result + fn upsert(conn: &PgConnection, user_form: &Self::Form) -> Result where Self: Sized; } diff --git a/crates/db_queries/src/source/activity.rs b/crates/db_queries/src/source/activity.rs index f87cf7330..1f158370e 100644 --- a/crates/db_queries/src/source/activity.rs +++ b/crates/db_queries/src/source/activity.rs @@ -9,7 +9,9 @@ use std::{ io::{Error as IoError, ErrorKind}, }; -impl Crud for Activity { +impl Crud for Activity { + type Form = ActivityForm; + type IdType = i32; fn read(conn: &PgConnection, activity_id: i32) -> Result { use lemmy_db_schema::schema::activity::dsl::*; activity.find(activity_id).first::(conn) diff --git a/crates/db_queries/src/source/comment.rs b/crates/db_queries/src/source/comment.rs index d0171cb8d..1e9722714 100644 --- a/crates/db_queries/src/source/comment.rs +++ b/crates/db_queries/src/source/comment.rs @@ -135,7 +135,9 @@ impl Comment_ for Comment { } } -impl Crud for Comment { +impl Crud for Comment { + type Form = CommentForm; + type IdType = CommentId; fn read(conn: &PgConnection, comment_id: CommentId) -> Result { use lemmy_db_schema::schema::comment::dsl::*; comment.find(comment_id).first::(conn) @@ -165,7 +167,8 @@ impl Crud for Comment { } } -impl ApubObject for Comment { +impl ApubObject for Comment { + type Form = CommentForm; fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result { use lemmy_db_schema::schema::comment::dsl::*; comment.filter(ap_id.eq(object_id)).first::(conn) @@ -182,7 +185,9 @@ impl ApubObject for Comment { } } -impl Likeable for CommentLike { +impl Likeable for CommentLike { + type Form = CommentLikeForm; + type IdType = CommentId; fn like(conn: &PgConnection, comment_like_form: &CommentLikeForm) -> Result { use lemmy_db_schema::schema::comment_like::dsl::*; insert_into(comment_like) @@ -207,7 +212,8 @@ impl Likeable for CommentLike { } } -impl Saveable for CommentSaved { +impl Saveable for CommentSaved { + type Form = CommentSavedForm; fn save(conn: &PgConnection, comment_saved_form: &CommentSavedForm) -> Result { use lemmy_db_schema::schema::comment_saved::dsl::*; insert_into(comment_saved) diff --git a/crates/db_queries/src/source/comment_report.rs b/crates/db_queries/src/source/comment_report.rs index 87b936062..738ec3e29 100644 --- a/crates/db_queries/src/source/comment_report.rs +++ b/crates/db_queries/src/source/comment_report.rs @@ -6,7 +6,8 @@ use lemmy_db_schema::{ PersonId, }; -impl Reportable for CommentReport { +impl Reportable for CommentReport { + type Form = CommentReportForm; /// creates a comment report and returns it /// /// * `conn` - the postgres connection diff --git a/crates/db_queries/src/source/community.rs b/crates/db_queries/src/source/community.rs index 2a6219339..eaaa2ba29 100644 --- a/crates/db_queries/src/source/community.rs +++ b/crates/db_queries/src/source/community.rs @@ -60,7 +60,9 @@ mod safe_type { } } -impl Crud for Community { +impl Crud for Community { + type Form = CommunityForm; + type IdType = CommunityId; fn read(conn: &PgConnection, community_id: CommunityId) -> Result { use lemmy_db_schema::schema::community::dsl::*; community.find(community_id).first::(conn) @@ -90,7 +92,8 @@ impl Crud for Community { } } -impl ApubObject for Community { +impl ApubObject for Community { + type Form = CommunityForm; fn read_from_apub_id(conn: &PgConnection, for_actor_id: &DbUrl) -> Result { use lemmy_db_schema::schema::community::dsl::*; community @@ -175,7 +178,8 @@ impl Community_ for Community { } } -impl Joinable for CommunityModerator { +impl Joinable for CommunityModerator { + type Form = CommunityModeratorForm; fn join( conn: &PgConnection, community_moderator_form: &CommunityModeratorForm, @@ -252,7 +256,8 @@ impl CommunityModerator_ for CommunityModerator { } } -impl Bannable for CommunityPersonBan { +impl Bannable for CommunityPersonBan { + type Form = CommunityPersonBanForm; fn ban( conn: &PgConnection, community_person_ban_form: &CommunityPersonBanForm, @@ -277,7 +282,8 @@ impl Bannable for CommunityPersonBan { } } -impl Followable for CommunityFollower { +impl Followable for CommunityFollower { + type Form = CommunityFollowerForm; fn follow( conn: &PgConnection, community_follower_form: &CommunityFollowerForm, diff --git a/crates/db_queries/src/source/local_user.rs b/crates/db_queries/src/source/local_user.rs index b711c82aa..91eac3308 100644 --- a/crates/db_queries/src/source/local_user.rs +++ b/crates/db_queries/src/source/local_user.rs @@ -91,7 +91,9 @@ impl LocalUser_ for LocalUser { } } -impl Crud for LocalUser { +impl Crud for LocalUser { + type Form = LocalUserForm; + type IdType = LocalUserId; fn read(conn: &PgConnection, local_user_id: LocalUserId) -> Result { local_user.find(local_user_id).first::(conn) } diff --git a/crates/db_queries/src/source/moderator.rs b/crates/db_queries/src/source/moderator.rs index 14bb07f1c..25ef1416d 100644 --- a/crates/db_queries/src/source/moderator.rs +++ b/crates/db_queries/src/source/moderator.rs @@ -2,7 +2,9 @@ use crate::Crud; use diesel::{dsl::*, result::Error, *}; use lemmy_db_schema::source::moderator::*; -impl Crud for ModRemovePost { +impl Crud for ModRemovePost { + type Form = ModRemovePostForm; + type IdType = i32; fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_remove_post::dsl::*; mod_remove_post.find(from_id).first::(conn) @@ -23,7 +25,9 @@ impl Crud for ModRemovePost { } } -impl Crud for ModLockPost { +impl Crud for ModLockPost { + type Form = ModLockPostForm; + type IdType = i32; fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_lock_post::dsl::*; mod_lock_post.find(from_id).first::(conn) @@ -44,7 +48,9 @@ impl Crud for ModLockPost { } } -impl Crud for ModStickyPost { +impl Crud for ModStickyPost { + type Form = ModStickyPostForm; + type IdType = i32; fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_sticky_post::dsl::*; mod_sticky_post.find(from_id).first::(conn) @@ -65,7 +71,9 @@ impl Crud for ModStickyPost { } } -impl Crud for ModRemoveComment { +impl Crud for ModRemoveComment { + type Form = ModRemoveCommentForm; + type IdType = i32; fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_remove_comment::dsl::*; mod_remove_comment.find(from_id).first::(conn) @@ -86,7 +94,9 @@ impl Crud for ModRemoveComment { } } -impl Crud for ModRemoveCommunity { +impl Crud for ModRemoveCommunity { + type Form = ModRemoveCommunityForm; + type IdType = i32; fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_remove_community::dsl::*; mod_remove_community.find(from_id).first::(conn) @@ -111,7 +121,9 @@ impl Crud for ModRemoveCommunity { } } -impl Crud for ModBanFromCommunity { +impl Crud for ModBanFromCommunity { + type Form = ModBanFromCommunityForm; + type IdType = i32; fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_ban_from_community::dsl::*; mod_ban_from_community.find(from_id).first::(conn) @@ -136,7 +148,9 @@ impl Crud for ModBanFromCommunity { } } -impl Crud for ModBan { +impl Crud for ModBan { + type Form = ModBanForm; + type IdType = i32; fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_ban::dsl::*; mod_ban.find(from_id).first::(conn) @@ -155,7 +169,9 @@ impl Crud for ModBan { } } -impl Crud for ModAddCommunity { +impl Crud for ModAddCommunity { + type Form = ModAddCommunityForm; + type IdType = i32; fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_add_community::dsl::*; mod_add_community.find(from_id).first::(conn) @@ -176,7 +192,9 @@ impl Crud for ModAddCommunity { } } -impl Crud for ModAdd { +impl Crud for ModAdd { + type Form = ModAddForm; + type IdType = i32; fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_add::dsl::*; mod_add.find(from_id).first::(conn) diff --git a/crates/db_queries/src/source/password_reset_request.rs b/crates/db_queries/src/source/password_reset_request.rs index d04a1ac4b..a71cdae26 100644 --- a/crates/db_queries/src/source/password_reset_request.rs +++ b/crates/db_queries/src/source/password_reset_request.rs @@ -7,7 +7,9 @@ use lemmy_db_schema::{ }; use sha2::{Digest, Sha256}; -impl Crud for PasswordResetRequest { +impl Crud for PasswordResetRequest { + type Form = PasswordResetRequestForm; + type IdType = i32; fn read(conn: &PgConnection, password_reset_request_id: i32) -> Result { password_reset_request .find(password_reset_request_id) diff --git a/crates/db_queries/src/source/person.rs b/crates/db_queries/src/source/person.rs index a7266aa27..6172b4e1e 100644 --- a/crates/db_queries/src/source/person.rs +++ b/crates/db_queries/src/source/person.rs @@ -158,7 +158,9 @@ mod safe_type_alias_2 { } } -impl Crud for Person { +impl Crud for Person { + type Form = PersonForm; + type IdType = PersonId; fn read(conn: &PgConnection, person_id: PersonId) -> Result { person .filter(deleted.eq(false)) @@ -178,7 +180,8 @@ impl Crud for Person { } } -impl ApubObject for Person { +impl ApubObject for Person { + type Form = PersonForm; fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result { use lemmy_db_schema::schema::person::dsl::*; person diff --git a/crates/db_queries/src/source/person_mention.rs b/crates/db_queries/src/source/person_mention.rs index 456894200..774f79185 100644 --- a/crates/db_queries/src/source/person_mention.rs +++ b/crates/db_queries/src/source/person_mention.rs @@ -2,7 +2,9 @@ use crate::Crud; use diesel::{dsl::*, result::Error, *}; use lemmy_db_schema::{source::person_mention::*, PersonId, PersonMentionId}; -impl Crud for PersonMention { +impl Crud for PersonMention { + type Form = PersonMentionForm; + type IdType = PersonMentionId; fn read(conn: &PgConnection, person_mention_id: PersonMentionId) -> Result { use lemmy_db_schema::schema::person_mention::dsl::*; person_mention.find(person_mention_id).first::(conn) diff --git a/crates/db_queries/src/source/post.rs b/crates/db_queries/src/source/post.rs index f0cf10935..02ae4d6e2 100644 --- a/crates/db_queries/src/source/post.rs +++ b/crates/db_queries/src/source/post.rs @@ -18,7 +18,9 @@ use lemmy_db_schema::{ PostId, }; -impl Crud for Post { +impl Crud for Post { + type Form = PostForm; + type IdType = PostId; fn read(conn: &PgConnection, post_id: PostId) -> Result { use lemmy_db_schema::schema::post::dsl::*; post.find(post_id).first::(conn) @@ -179,7 +181,8 @@ impl Post_ for Post { } } -impl ApubObject for Post { +impl ApubObject for Post { + type Form = PostForm; fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result { use lemmy_db_schema::schema::post::dsl::*; post.filter(ap_id.eq(object_id)).first::(conn) @@ -196,7 +199,9 @@ impl ApubObject for Post { } } -impl Likeable for PostLike { +impl Likeable for PostLike { + type Form = PostLikeForm; + type IdType = PostId; fn like(conn: &PgConnection, post_like_form: &PostLikeForm) -> Result { use lemmy_db_schema::schema::post_like::dsl::*; insert_into(post_like) @@ -217,7 +222,8 @@ impl Likeable for PostLike { } } -impl Saveable for PostSaved { +impl Saveable for PostSaved { + type Form = PostSavedForm; fn save(conn: &PgConnection, post_saved_form: &PostSavedForm) -> Result { use lemmy_db_schema::schema::post_saved::dsl::*; insert_into(post_saved) @@ -238,7 +244,8 @@ impl Saveable for PostSaved { } } -impl Readable for PostRead { +impl Readable for PostRead { + type Form = PostReadForm; fn mark_as_read(conn: &PgConnection, post_read_form: &PostReadForm) -> Result { use lemmy_db_schema::schema::post_read::dsl::*; insert_into(post_read) diff --git a/crates/db_queries/src/source/post_report.rs b/crates/db_queries/src/source/post_report.rs index b4e855731..19cd5dfea 100644 --- a/crates/db_queries/src/source/post_report.rs +++ b/crates/db_queries/src/source/post_report.rs @@ -2,7 +2,8 @@ use crate::Reportable; use diesel::{dsl::*, result::Error, *}; use lemmy_db_schema::{naive_now, source::post_report::*, PersonId}; -impl Reportable for PostReport { +impl Reportable for PostReport { + type Form = PostReportForm; /// creates a post report and returns it /// /// * `conn` - the postgres connection diff --git a/crates/db_queries/src/source/private_message.rs b/crates/db_queries/src/source/private_message.rs index da1c5abd5..c1138b979 100644 --- a/crates/db_queries/src/source/private_message.rs +++ b/crates/db_queries/src/source/private_message.rs @@ -2,7 +2,9 @@ use crate::{ApubObject, Crud, DeleteableOrRemoveable}; use diesel::{dsl::*, result::Error, *}; use lemmy_db_schema::{naive_now, source::private_message::*, DbUrl, PersonId, PrivateMessageId}; -impl Crud for PrivateMessage { +impl Crud for PrivateMessage { + type Form = PrivateMessageForm; + type IdType = PrivateMessageId; fn read(conn: &PgConnection, private_message_id: PrivateMessageId) -> Result { use lemmy_db_schema::schema::private_message::dsl::*; private_message.find(private_message_id).first::(conn) @@ -27,7 +29,8 @@ impl Crud for PrivateMessage { } } -impl ApubObject for PrivateMessage { +impl ApubObject for PrivateMessage { + type Form = PrivateMessageForm; fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result where Self: Sized, diff --git a/crates/db_queries/src/source/site.rs b/crates/db_queries/src/source/site.rs index d688546f8..b2bad7138 100644 --- a/crates/db_queries/src/source/site.rs +++ b/crates/db_queries/src/source/site.rs @@ -2,7 +2,9 @@ use crate::Crud; use diesel::{dsl::*, result::Error, *}; use lemmy_db_schema::{naive_now, source::site::*, PersonId}; -impl Crud for Site { +impl Crud for Site { + type Form = SiteForm; + type IdType = i32; fn read(conn: &PgConnection, _site_id: i32) -> Result { use lemmy_db_schema::schema::site::dsl::*; site.first::(conn) diff --git a/crates/websocket/Cargo.toml b/crates/websocket/Cargo.toml index 3571d0c32..6262beb50 100644 --- a/crates/websocket/Cargo.toml +++ b/crates/websocket/Cargo.toml @@ -15,6 +15,8 @@ lemmy_utils = { version = "=0.11.3", path = "../utils" } lemmy_api_common = { version = "=0.11.3", path = "../api_common" } lemmy_db_queries = { version = "=0.11.3", path = "../db_queries" } 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"] } log = "0.4.14" rand = "0.8.4" diff --git a/crates/websocket/src/lib.rs b/crates/websocket/src/lib.rs index f5f5f0804..b866a2a21 100644 --- a/crates/websocket/src/lib.rs +++ b/crates/websocket/src/lib.rs @@ -13,6 +13,7 @@ pub mod chat_server; pub mod handlers; pub mod messages; pub mod routes; +pub mod send; pub struct LemmyContext { pub pool: DbPool, diff --git a/crates/websocket/src/messages.rs b/crates/websocket/src/messages.rs index 1ef3da5b5..3c16ec273 100644 --- a/crates/websocket/src/messages.rs +++ b/crates/websocket/src/messages.rs @@ -75,7 +75,7 @@ pub struct SendModRoomMessage { #[derive(Message)] #[rtype(result = "()")] -pub struct SendPost { +pub(crate) struct SendPost { pub op: OP, pub post: PostResponse, pub websocket_id: Option, @@ -83,7 +83,7 @@ pub struct SendPost { #[derive(Message)] #[rtype(result = "()")] -pub struct SendComment { +pub(crate) struct SendComment { pub op: OP, pub comment: CommentResponse, pub websocket_id: Option, diff --git a/crates/websocket/src/send.rs b/crates/websocket/src/send.rs new file mode 100644 index 000000000..130d94a48 --- /dev/null +++ b/crates/websocket/src/send.rs @@ -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( + post_id: PostId, + op: OP, + websocket_id: Option, + person_id: Option, + context: &LemmyContext, +) -> Result { + 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( + comment_id: CommentId, + op: OP, + context: &LemmyContext, +) -> Result { + send_comment_ws_message(comment_id, op, None, None, None, vec![], context).await +} + +pub async fn send_comment_ws_message( + comment_id: CommentId, + op: OP, + websocket_id: Option, + form_id: Option, + person_id: Option, + recipient_ids: Vec, + context: &LemmyContext, +) -> Result { + 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( + community_id: CommunityId, + op: OP, + websocket_id: Option, + person_id: Option, + context: &LemmyContext, +) -> Result { + 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( + private_message_id: PrivateMessageId, + op: OP, + websocket_id: Option, + context: &LemmyContext, +) -> Result { + 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) +} From 1f64db6a33c80ecbf83c3041f9db8eb2663f9856 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Tue, 17 Aug 2021 16:31:16 -0400 Subject: [PATCH 6/9] Upgrading deps --- Cargo.lock | 264 +++++++++++---------------- Cargo.toml | 15 +- crates/api/Cargo.toml | 16 +- crates/api_common/Cargo.toml | 6 +- crates/api_crud/Cargo.toml | 16 +- crates/apub/Cargo.toml | 17 +- crates/apub_lib/Cargo.toml | 9 +- crates/apub_lib_derive/Cargo.toml | 8 +- crates/db_queries/Cargo.toml | 6 +- crates/db_schema/Cargo.toml | 4 +- crates/db_views/Cargo.toml | 2 +- crates/db_views_actor/Cargo.toml | 2 +- crates/db_views_moderator/Cargo.toml | 2 +- crates/routes/Cargo.toml | 4 +- crates/utils/Cargo.toml | 16 +- crates/websocket/Cargo.toml | 8 +- docker/dev/Dockerfile | 2 +- docker/prod/Dockerfile | 2 +- 18 files changed, 171 insertions(+), 228 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 844d49e10..d859f2745 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,17 +16,6 @@ dependencies = [ "url", ] -[[package]] -name = "activitystreams-ext" -version = "0.1.0-alpha.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb8e19a0810cc25df3535061a08b7d8f8a734d309ea4411c57a9767e4a2ffa0e" -dependencies = [ - "activitystreams", - "serde", - "serde_json", -] - [[package]] name = "actix" version = "0.12.0" @@ -115,7 +104,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2f86cd6857c135e6e9fe57b1619a88d1f94a7df34c00e11fe13e64fd3438837" dependencies = [ "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -264,9 +253,9 @@ version = "0.5.0-beta.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d048c6986743105c1e8e9729fbc8d5d1667f2f62393a58be8d85a7d9a5a6c8d" dependencies = [ - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -275,18 +264,9 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d44b8fee1ced9671ba043476deddef739dd0959bf77030b26b738cc591737a7" dependencies = [ - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", -] - -[[package]] -name = "addr2line" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a2e47a1fbe209ee101dd6d61285226744c6c8d3c21c8dc878ba6cb9f467f3a" -dependencies = [ - "gimli", + "syn 1.0.74", ] [[package]] @@ -329,9 +309,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.41" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61" +checksum = "28ae2b3dec75a406790005a200b1bd89785afc02517a00ca99ecfe093ee9e6cf" [[package]] name = "async-mutex" @@ -344,13 +324,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.50" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722" +checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e" dependencies = [ - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -458,21 +438,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "backtrace" -version = "0.3.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7815ea54e4d821e791162e078acbebfd6d8c8939cd559c9335dceb1c8ca7282" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide 0.4.4", - "object", - "rustc-demangle", -] - [[package]] name = "base-x" version = "0.2.8" @@ -493,9 +458,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bcrypt" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff61734d6bd86e9739fe61bce08b753ae61ae76101dc2df8399eda2503d5a29" +checksum = "f691e63585950d8c1c43644d11bab9073e40f5060dd2822734ae7c3dc69a3a80" dependencies = [ "base64 0.13.0", "blowfish", @@ -672,9 +637,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "comrak" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b423acba50d5016684beaf643f9991e622633a4c858be6885653071c2da2b0c6" +checksum = "17bac331cb476d0d005a492e07a5eb64f8b321e3788b1fb265e768fb6918ea13" dependencies = [ "entities", "lazy_static", @@ -817,10 +782,10 @@ checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", "strsim 0.9.3", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -831,10 +796,10 @@ checksum = "2c34d8efb62d0c2d7f60ece80f75e5c63c1588ba68032740494b0b9a996466e3" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", "strsim 0.10.0", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -845,7 +810,7 @@ checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" dependencies = [ "darling_core 0.10.2", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -856,7 +821,7 @@ checksum = "ade7bff147130fe5e6d39f089c6bd49ec0250f35d70b2eebf72afdfc919f15cc" dependencies = [ "darling_core 0.13.0", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -877,9 +842,9 @@ checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0" dependencies = [ "darling 0.10.2", "derive_builder_core", - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -889,9 +854,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef" dependencies = [ "darling 0.10.2", - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -901,16 +866,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cc7b9cef1e351660e5443924e4f43ab25fbbed3e9a5f052df3677deb4d6b320" dependencies = [ "convert_case", - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] name = "deser-hjson" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf2973e4fb5f11bb10cc56814ce30e9721ced195cec313a80c94ce29c2f0e896" +checksum = "1f486ff51f3ecdf9364736375a4b358b6eb9f02555d5324fa4837c00b5aa23f5" dependencies = [ "serde", ] @@ -948,9 +913,9 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" dependencies = [ - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -1025,9 +990,9 @@ checksum = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca" [[package]] name = "env_logger" -version = "0.8.4" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" dependencies = [ "atty", "humantime", @@ -1117,9 +1082,9 @@ checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" [[package]] name = "futures" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7e43a803dae2fa37c1f6a8fe121e1f7bf9548b4dfc0522a42f34145dadfc27" +checksum = "1adc00f486adfc9ce99f77d717836f0c5aa84965eb0b4f051f4e83f7cab53f8b" dependencies = [ "futures-channel", "futures-core", @@ -1132,9 +1097,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2" +checksum = "74ed2411805f6e4e3d9bc904c95d5d423b89b3b25dc0250aa74729de20629ff9" dependencies = [ "futures-core", "futures-sink", @@ -1142,15 +1107,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1" +checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99" [[package]] name = "futures-executor" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79" +checksum = "4d0d535a57b87e1ae31437b892713aee90cd2d7b0ee48727cd11fc72ef54761c" dependencies = [ "futures-core", "futures-task", @@ -1159,40 +1124,40 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acc499defb3b348f8d8f3f66415835a9131856ff7714bf10dadfc4ec4bdb29a1" +checksum = "0b0e06c393068f3a6ef246c75cdca793d6a46347e75286933e5e75fd2fd11582" [[package]] name = "futures-macro" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121" +checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57" dependencies = [ "autocfg", "proc-macro-hack", - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] name = "futures-sink" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a57bead0ceff0d6dde8f465ecd96c9338121bb7717d3e7b108059531870c4282" +checksum = "c0f30aaa67363d119812743aa5f33c201a7a66329f97d1a887022971feea4b53" [[package]] name = "futures-task" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a16bef9fc1a4dddb5bee51c989e3fbba26569cbb0e31f5b303c184e3dd33dae" +checksum = "bbe54a98670017f3be909561f6ad13e810d9a51f3f061b902062ca3da80799f2" [[package]] name = "futures-util" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967" +checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78" dependencies = [ "autocfg", "futures-channel", @@ -1260,12 +1225,6 @@ dependencies = [ "weezl", ] -[[package]] -name = "gimli" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4075386626662786ddb0ec9081e7c7eeb1ba31951f447ca780ef9f5d568189" - [[package]] name = "glob" version = "0.3.0" @@ -1703,7 +1662,6 @@ dependencies = [ "async-trait", "awc", "background-jobs", - "backtrace", "base64 0.13.0", "bcrypt", "chrono", @@ -1744,7 +1702,6 @@ name = "lemmy_apub_lib" version = "0.11.3" dependencies = [ "activitystreams", - "activitystreams-ext", "async-trait", "lemmy_apub_lib_derive", "lemmy_utils", @@ -1758,9 +1715,9 @@ dependencies = [ name = "lemmy_apub_lib_derive" version = "0.11.3" dependencies = [ - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", "trybuild", ] @@ -2080,9 +2037,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c" dependencies = [ "migrations_internals", - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -2233,15 +2190,6 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.8.0" @@ -2262,9 +2210,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.35" +version = "0.10.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "549430950c79ae24e6d02e0b7404534ecf311d94cc9f861e9e4020187d13d885" +checksum = "8d9facdb76fec0b73c406f125d44d86fdad818d66fef0531eec9233ca425ff4a" dependencies = [ "bitflags", "cfg-if", @@ -2282,9 +2230,9 @@ checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" [[package]] name = "openssl-sys" -version = "0.9.65" +version = "0.9.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a7907e3bfa08bb85105209cdfcb6c63d109f8f6c1ed6ca318fff5c1853fbc1d" +checksum = "1996d2d305e561b70d1ee0c53f1542833f4e1ac6ce9a6708b6ff2738ca67dc82" dependencies = [ "autocfg", "cc", @@ -2368,9 +2316,9 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -2399,9 +2347,9 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f" dependencies = [ - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -2472,9 +2420,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" +checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" dependencies = [ "unicode-xid 0.2.2", ] @@ -2504,7 +2452,7 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", ] [[package]] @@ -2741,12 +2689,6 @@ dependencies = [ "quick-xml", ] -[[package]] -name = "rustc-demangle" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49" - [[package]] name = "rustc_version" version = "0.2.3" @@ -2862,29 +2804,29 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.126" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" +checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.126" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" +checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc" dependencies = [ - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] name = "serde_json" -version = "1.0.64" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127" dependencies = [ "indexmap", "itoa", @@ -2922,9 +2864,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1569374bd54623ec8bd592cf22ba6e03c0f177ff55fbc8c29a49e296e7adecf" dependencies = [ "darling 0.13.0", - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -2944,9 +2886,9 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5" dependencies = [ - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -3037,9 +2979,9 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6" dependencies = [ - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -3087,11 +3029,11 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" dependencies = [ - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", "serde", "serde_derive", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -3101,13 +3043,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" dependencies = [ "base-x", - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", "serde", "serde_derive", "serde_json", "sha1", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -3141,9 +3083,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec" dependencies = [ "heck", - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -3159,11 +3101,11 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.73" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" +checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" dependencies = [ - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", "unicode-xid 0.2.2", ] @@ -3212,9 +3154,9 @@ version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745" dependencies = [ - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -3271,10 +3213,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" dependencies = [ "proc-macro-hack", - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", "standback", - "syn 1.0.73", + "syn 1.0.74", ] [[package]] @@ -3294,9 +3236,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "570c2eb13b3ab38208130eccd41be92520388791207fde783bda7c1e8ace28d4" +checksum = "01cf844b23c6131f624accf65ce0e4e9956a8bb329400ea5bcc26ae3a5c20b0b" dependencies = [ "autocfg", "bytes", @@ -3388,9 +3330,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "trybuild" -version = "1.0.42" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1768998d9a3b179411618e377dbb134c58a88cda284b0aa71c42c40660127d46" +checksum = "5bdaf2a1d317f3d58b44b31c7f6436b9b9acafe7bddfeace50897c2b804d7792" dependencies = [ "dissimilar", "glob", @@ -3561,9 +3503,9 @@ dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", "wasm-bindgen-shared", ] @@ -3595,9 +3537,9 @@ version = "0.2.74" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" dependencies = [ - "proc-macro2 1.0.27", + "proc-macro2 1.0.28", "quote 1.0.9", - "syn 1.0.73", + "syn 1.0.74", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/Cargo.toml b/Cargo.toml index 5cf815404..be1fd4128 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,24 +47,27 @@ lemmy_routes = { version = "=0.11.3", path = "./crates/routes" } diesel = "1.4.7" diesel_migrations = "1.4.0" chrono = { version = "0.4.19", features = ["serde"] } -serde = { version = "1.0.126", features = ["derive"] } +serde = { version = "1.0.127", features = ["derive"] } actix = "0.12.0" actix-web = { version = "4.0.0-beta.8", default-features = false, features = ["rustls"] } log = "0.4.14" -env_logger = "0.8.4" +env_logger = "0.9.0" strum = "0.21.0" url = { version = "2.2.2", features = ["serde"] } -openssl = "0.10.35" +openssl = "0.10.36" http-signature-normalization-actix = { version = "0.5.0-beta.7", default-features = false, features = ["sha-2"] } -tokio = { version = "1.8.0", features = ["sync"] } -anyhow = "1.0.41" +tokio = { version = "1.10.0", features = ["sync"] } +anyhow = "1.0.43" reqwest = { version = "0.11.4", features = ["json"] } activitystreams = "0.7.0-alpha.11" actix-rt = { version = "2.2.0", default-features = false } -serde_json = { version = "1.0.64", features = ["preserve_order"] } +serde_json = { version = "1.0.66", features = ["preserve_order"] } clokwerk = "0.3.5" [dev-dependencies.cargo-husky] version = "1.5.0" default-features = false # Disable features which are enabled by default features = ["precommit-hook", "run-cargo-fmt", "run-cargo-clippy"] + +[package.metadata.cargo-udeps.ignore] +development = ["cargo-husky"] diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml index f7adb99ef..f56b8f2e1 100644 --- a/crates/api/Cargo.toml +++ b/crates/api/Cargo.toml @@ -21,10 +21,10 @@ lemmy_db_views_actor = { version = "=0.11.3", path = "../db_views_actor" } lemmy_api_common = { version = "=0.11.3", path = "../api_common" } lemmy_websocket = { version = "=0.11.3", path = "../websocket" } diesel = "1.4.7" -bcrypt = "0.10.0" +bcrypt = "0.10.1" chrono = { version = "0.4.19", features = ["serde"] } -serde_json = { version = "1.0.64", features = ["preserve_order"] } -serde = { version = "1.0.126", features = ["derive"] } +serde_json = { version = "1.0.66", features = ["preserve_order"] } +serde = { version = "1.0.127", features = ["derive"] } actix = "0.12.0" actix-web = { version = "4.0.0-beta.8", default-features = false } actix-rt = { version = "2.2.0", default-features = false } @@ -35,18 +35,18 @@ strum = "0.21.0" strum_macros = "0.21.1" lazy_static = "1.4.0" url = { version = "2.2.2", features = ["serde"] } -openssl = "0.10.35" +openssl = "0.10.36" http = "0.2.4" http-signature-normalization-actix = { version = "0.5.0-beta.7", default-features = false, features = ["sha-2"] } base64 = "0.13.0" -tokio = "1.8.0" -futures = "0.3.15" +tokio = "1.10.0" +futures = "0.3.16" itertools = "0.10.1" uuid = { version = "0.8.2", features = ["serde", "v4"] } sha2 = "0.9.5" -async-trait = "0.1.50" +async-trait = "0.1.51" captcha = "0.0.8" -anyhow = "1.0.41" +anyhow = "1.0.43" thiserror = "1.0.26" background-jobs = "0.9.0" reqwest = { version = "0.11.4", features = ["json"] } diff --git a/crates/api_common/Cargo.toml b/crates/api_common/Cargo.toml index 02d33f6fe..05bbf97af 100644 --- a/crates/api_common/Cargo.toml +++ b/crates/api_common/Cargo.toml @@ -17,10 +17,10 @@ lemmy_db_views_moderator = { version = "=0.11.3", path = "../db_views_moderator" lemmy_db_views_actor = { version = "=0.11.3", path = "../db_views_actor" } lemmy_db_schema = { version = "=0.11.3", path = "../db_schema" } lemmy_utils = { version = "=0.11.3", path = "../utils" } -serde = { version = "1.0.126", features = ["derive"] } +serde = { version = "1.0.127", features = ["derive"] } log = "0.4.14" diesel = "1.4.7" -actix-web = {version = "4.0.0-beta.8", default-features = false, features = ["cookies"] } +actix-web = { version = "4.0.0-beta.8", default-features = false, features = ["cookies"] } chrono = { version = "0.4.19", features = ["serde"] } -serde_json = { version = "1.0.64", features = ["preserve_order"] } +serde_json = { version = "1.0.66", features = ["preserve_order"] } url = "2.2.2" diff --git a/crates/api_crud/Cargo.toml b/crates/api_crud/Cargo.toml index 47746d0dd..563ae8d08 100644 --- a/crates/api_crud/Cargo.toml +++ b/crates/api_crud/Cargo.toml @@ -16,10 +16,10 @@ lemmy_db_views_actor = { version = "=0.11.3", path = "../db_views_actor" } lemmy_api_common = { version = "=0.11.3", path = "../api_common" } lemmy_websocket = { version = "=0.11.3", path = "../websocket" } diesel = "1.4.7" -bcrypt = "0.10.0" +bcrypt = "0.10.1" chrono = { version = "0.4.19", features = ["serde"] } -serde_json = { version = "1.0.64", features = ["preserve_order"] } -serde = { version = "1.0.126", features = ["derive"] } +serde_json = { version = "1.0.66", features = ["preserve_order"] } +serde = { version = "1.0.127", features = ["derive"] } actix = "0.12.0" actix-web = { version = "4.0.0-beta.8", default-features = false } actix-rt = { version = "2.2.0", default-features = false } @@ -30,17 +30,17 @@ strum = "0.21.0" strum_macros = "0.21.1" lazy_static = "1.4.0" url = { version = "2.2.2", features = ["serde"] } -openssl = "0.10.35" +openssl = "0.10.36" http = "0.2.4" http-signature-normalization-actix = { version = "0.5.0-beta.7", default-features = false, features = ["sha-2"] } base64 = "0.13.0" -tokio = "1.8.0" -futures = "0.3.15" +tokio = "1.10.0" +futures = "0.3.16" itertools = "0.10.1" uuid = { version = "0.8.2", features = ["serde", "v4"] } sha2 = "0.9.5" -async-trait = "0.1.50" -anyhow = "1.0.41" +async-trait = "0.1.51" +anyhow = "1.0.43" thiserror = "1.0.26" background-jobs = "0.9.0" reqwest = { version = "0.11.4", features = ["json"] } diff --git a/crates/apub/Cargo.toml b/crates/apub/Cargo.toml index e0c714c10..c8305e44f 100644 --- a/crates/apub/Cargo.toml +++ b/crates/apub/Cargo.toml @@ -21,10 +21,10 @@ lemmy_api_common = { version = "=0.11.3", path = "../api_common" } lemmy_websocket = { version = "=0.11.3", path = "../websocket" } diesel = "1.4.7" activitystreams = "0.7.0-alpha.11" -bcrypt = "0.10.0" +bcrypt = "0.10.1" chrono = { version = "0.4.19", features = ["serde"] } -serde_json = { version = "1.0.64", features = ["preserve_order"] } -serde = { version = "1.0.126", features = ["derive"] } +serde_json = { version = "1.0.66", features = ["preserve_order"] } +serde = { version = "1.0.127", features = ["derive"] } serde_with = "1.9.4" actix = "0.12.0" actix-web = { version = "4.0.0-beta.8", default-features = false } @@ -36,21 +36,20 @@ strum = "0.21.0" strum_macros = "0.21.1" url = { version = "2.2.2", features = ["serde"] } percent-encoding = "2.1.0" -openssl = "0.10.35" +openssl = "0.10.36" http = "0.2.4" http-signature-normalization-actix = { version = "0.5.0-beta.7", default-features = false, features = ["sha-2"] } http-signature-normalization-reqwest = { version = "0.2.0", default-features = false, features = ["sha-2"] } base64 = "0.13.0" -tokio = "1.8.0" -futures = "0.3.15" +tokio = "1.10.0" +futures = "0.3.16" itertools = "0.10.1" uuid = { version = "0.8.2", features = ["serde", "v4"] } sha2 = "0.9.5" -async-trait = "0.1.50" -anyhow = "1.0.41" +async-trait = "0.1.51" +anyhow = "1.0.43" thiserror = "1.0.26" background-jobs = "0.9.0" reqwest = { version = "0.11.4", features = ["json"] } -backtrace = "0.3.60" lazy_static = "1.4.0" diff --git a/crates/apub_lib/Cargo.toml b/crates/apub_lib/Cargo.toml index 7bc2f125e..2593cd94e 100644 --- a/crates/apub_lib/Cargo.toml +++ b/crates/apub_lib/Cargo.toml @@ -10,8 +10,7 @@ lemmy_utils = { version = "=0.11.3", path = "../utils" } lemmy_websocket = { version = "=0.11.3", path = "../websocket" } lemmy_apub_lib_derive = { version = "=0.11.3", path = "../apub_lib_derive" } activitystreams = "0.7.0-alpha.11" -activitystreams-ext = "0.1.0-alpha.2" -serde = { version = "1.0.123", features = ["derive"] } -async-trait = "0.1.42" -url = { version = "2.2.1", features = ["serde"] } -serde_json = { version = "1.0.64", features = ["preserve_order"] } +serde = { version = "1.0.127", features = ["derive"] } +async-trait = "0.1.51" +url = { version = "2.2.2", features = ["serde"] } +serde_json = { version = "1.0.66", features = ["preserve_order"] } diff --git a/crates/apub_lib_derive/Cargo.toml b/crates/apub_lib_derive/Cargo.toml index 3b1e2a9eb..5ad598409 100644 --- a/crates/apub_lib_derive/Cargo.toml +++ b/crates/apub_lib_derive/Cargo.toml @@ -9,9 +9,9 @@ license = "AGPL-3.0" proc-macro = true [dev-dependencies] -trybuild = { version = "1.0", features = ["diff"] } +trybuild = { version = "1.0.45", features = ["diff"] } [dependencies] -proc-macro2 = "1.0" -syn = "1.0" -quote = "1.0" +proc-macro2 = "1.0.28" +syn = "1.0.74" +quote = "1.0.9" diff --git a/crates/db_queries/Cargo.toml b/crates/db_queries/Cargo.toml index 61384ee28..50199ea3e 100644 --- a/crates/db_queries/Cargo.toml +++ b/crates/db_queries/Cargo.toml @@ -16,8 +16,8 @@ lemmy_db_schema = { version = "=0.11.3", path = "../db_schema" } diesel = { version = "1.4.7", features = ["postgres","chrono","r2d2","serde_json"] } diesel_migrations = "1.4.0" chrono = { version = "0.4.19", features = ["serde"] } -serde = { version = "1.0.126", features = ["derive"] } -serde_json = { version = "1.0.64", features = ["preserve_order"] } +serde = { version = "1.0.127", features = ["derive"] } +serde_json = { version = "1.0.66", features = ["preserve_order"] } strum = "0.21.0" strum_macros = "0.21.1" log = "0.4.14" @@ -25,7 +25,7 @@ sha2 = "0.9.5" url = { version = "2.2.2", features = ["serde"] } lazy_static = "1.4.0" regex = "1.5.4" -bcrypt = "0.10.0" +bcrypt = "0.10.1" [dev-dependencies] serial_test = "0.5.1" diff --git a/crates/db_schema/Cargo.toml b/crates/db_schema/Cargo.toml index 6bf5ac3cc..969382b84 100644 --- a/crates/db_schema/Cargo.toml +++ b/crates/db_schema/Cargo.toml @@ -11,8 +11,8 @@ doctest = false [dependencies] diesel = { version = "1.4.7", features = ["postgres","chrono","r2d2","serde_json"] } chrono = { version = "0.4.19", features = ["serde"] } -serde = { version = "1.0.126", features = ["derive"] } -serde_json = { version = "1.0.64", features = ["preserve_order"] } +serde = { version = "1.0.127", features = ["derive"] } +serde_json = { version = "1.0.66", features = ["preserve_order"] } log = "0.4.14" url = { version = "2.2.2", features = ["serde"] } diesel-derive-newtype = "0.1.2" diff --git a/crates/db_views/Cargo.toml b/crates/db_views/Cargo.toml index f8395ce2f..7044b6659 100644 --- a/crates/db_views/Cargo.toml +++ b/crates/db_views/Cargo.toml @@ -12,7 +12,7 @@ doctest = false lemmy_db_queries = { version = "=0.11.3", path = "../db_queries" } lemmy_db_schema = { version = "=0.11.3", path = "../db_schema" } diesel = { version = "1.4.7", features = ["postgres","chrono","r2d2","serde_json"] } -serde = { version = "1.0.126", features = ["derive"] } +serde = { version = "1.0.127", features = ["derive"] } log = "0.4.14" url = "2.2.2" diff --git a/crates/db_views_actor/Cargo.toml b/crates/db_views_actor/Cargo.toml index bcd21e804..14741e408 100644 --- a/crates/db_views_actor/Cargo.toml +++ b/crates/db_views_actor/Cargo.toml @@ -12,4 +12,4 @@ doctest = false lemmy_db_queries = { version = "=0.11.3", path = "../db_queries" } lemmy_db_schema = { version = "=0.11.3", path = "../db_schema" } diesel = { version = "1.4.7", features = ["postgres","chrono","r2d2","serde_json"] } -serde = { version = "1.0.126", features = ["derive"] } +serde = { version = "1.0.127", features = ["derive"] } diff --git a/crates/db_views_moderator/Cargo.toml b/crates/db_views_moderator/Cargo.toml index 196e72c50..ba80dc0d4 100644 --- a/crates/db_views_moderator/Cargo.toml +++ b/crates/db_views_moderator/Cargo.toml @@ -12,4 +12,4 @@ doctest = false lemmy_db_queries = { version = "=0.11.3", path = "../db_queries" } lemmy_db_schema = { version = "=0.11.3", path = "../db_schema" } diesel = { version = "1.4.7", features = ["postgres","chrono","r2d2","serde_json"] } -serde = { version = "1.0.126", features = ["derive"] } +serde = { version = "1.0.127", features = ["derive"] } diff --git a/crates/routes/Cargo.toml b/crates/routes/Cargo.toml index fbecda492..a29172ac2 100644 --- a/crates/routes/Cargo.toml +++ b/crates/routes/Cargo.toml @@ -22,10 +22,10 @@ actix-web = { version = "4.0.0-beta.8", default-features = false, features = ["r actix-web-actors = { version = "4.0.0-beta.6", default-features = false } sha2 = "0.9.5" log = "0.4.14" -anyhow = "1.0.41" +anyhow = "1.0.43" chrono = { version = "0.4.19", features = ["serde"] } rss = "1.10.0" -serde = { version = "1.0.126", features = ["derive"] } +serde = { version = "1.0.127", features = ["derive"] } awc = { version = "3.0.0-beta.7", default-features = false } url = { version = "2.2.2", features = ["serde"] } strum = "0.21.0" diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml index d4e15707c..018ed52c9 100644 --- a/crates/utils/Cargo.toml +++ b/crates/utils/Cargo.toml @@ -18,23 +18,23 @@ log = "0.4.14" itertools = "0.10.1" rand = "0.8.4" percent-encoding = "2.1.0" -serde = { version = "1.0.126", features = ["derive"] } -serde_json = { version = "1.0.64", features = ["preserve_order"] } +serde = { version = "1.0.127", features = ["derive"] } +serde_json = { version = "1.0.66", features = ["preserve_order"] } thiserror = "1.0.26" -comrak = { version = "0.10.1", default-features = false } +comrak = { version = "0.11.0", default-features = false } lazy_static = "1.4.0" -openssl = "0.10.35" +openssl = "0.10.36" url = { version = "2.2.2", features = ["serde"] } actix-web = { version = "4.0.0-beta.8", default-features = false, features = ["rustls"] } actix-rt = { version = "2.2.0", default-features = false } -anyhow = "1.0.41" +anyhow = "1.0.43" reqwest = { version = "0.11.4", features = ["json"] } -tokio = { version = "1.8.0", features = ["sync"] } +tokio = { version = "1.10.0", features = ["sync"] } strum = "0.21.0" strum_macros = "0.21.1" -futures = "0.3.15" +futures = "0.3.16" diesel = "1.4.7" http = "0.2.4" jsonwebtoken = "7.2.0" -deser-hjson = "1.0.1" +deser-hjson = "1.0.2" smart-default = "0.6.0" diff --git a/crates/websocket/Cargo.toml b/crates/websocket/Cargo.toml index 6262beb50..0f5aa651d 100644 --- a/crates/websocket/Cargo.toml +++ b/crates/websocket/Cargo.toml @@ -20,13 +20,13 @@ lemmy_db_views_actor = { version = "=0.11.3", path = "../db_views_actor" } reqwest = { version = "0.11.4", features = ["json"] } log = "0.4.14" rand = "0.8.4" -serde = { version = "1.0.126", features = ["derive"] } -serde_json = { version = "1.0.64", features = ["preserve_order"] } +serde = { version = "1.0.127", features = ["derive"] } +serde_json = { version = "1.0.66", features = ["preserve_order"] } actix = "0.12.0" -anyhow = "1.0.41" +anyhow = "1.0.43" diesel = "1.4.7" background-jobs = "0.9.0" -tokio = "1.8.0" +tokio = "1.10.0" strum = "0.21.0" strum_macros = "0.21.1" chrono = { version = "0.4.19", features = ["serde"] } diff --git a/docker/dev/Dockerfile b/docker/dev/Dockerfile index 071d59e54..a5c305bd1 100644 --- a/docker/dev/Dockerfile +++ b/docker/dev/Dockerfile @@ -45,7 +45,7 @@ RUN strip ./target/$CARGO_BUILD_TARGET/$RUSTRELEASEDIR/lemmy_server RUN cp ./target/$CARGO_BUILD_TARGET/$RUSTRELEASEDIR/lemmy_server /app/lemmy_server # The alpine runner -FROM alpine:3.12 as lemmy +FROM alpine:3.14 as lemmy # Install libpq for postgres RUN apk add libpq diff --git a/docker/prod/Dockerfile b/docker/prod/Dockerfile index f6a2b06f6..dedd5ac0e 100644 --- a/docker/prod/Dockerfile +++ b/docker/prod/Dockerfile @@ -18,7 +18,7 @@ RUN strip ./target/$CARGO_BUILD_TARGET/$RUSTRELEASEDIR/lemmy_server RUN cp ./target/$CARGO_BUILD_TARGET/$RUSTRELEASEDIR/lemmy_server /app/lemmy_server # The alpine runner -FROM alpine:3.12 as lemmy +FROM alpine:3.14 as lemmy # Install libpq for postgres RUN apk add libpq From 6910e18a834afe13b381f39df44b58c6771125ae Mon Sep 17 00:00:00 2001 From: Dessalines Date: Tue, 17 Aug 2021 17:52:28 -0400 Subject: [PATCH 7/9] Adding ModTransferCommunity to modlog in API. Fixes #1437 --- crates/api/src/community.rs | 6 +- crates/api/src/site.rs | 7 ++ crates/api_common/src/site.rs | 2 + crates/db_queries/src/source/moderator.rs | 27 ++++++ crates/db_schema/src/schema.rs | 13 +++ crates/db_schema/src/source/moderator.rs | 21 +++++ crates/db_views_moderator/src/lib.rs | 1 + .../src/mod_transfer_community_view.rs | 85 +++++++++++++++++++ .../down.sql | 1 + .../up.sql | 9 ++ 10 files changed, 168 insertions(+), 4 deletions(-) create mode 100644 crates/db_views_moderator/src/mod_transfer_community_view.rs create mode 100644 migrations/2021-08-17-210508_create_mod_transfer_community/down.sql create mode 100644 migrations/2021-08-17-210508_create_mod_transfer_community/up.sql diff --git a/crates/api/src/community.rs b/crates/api/src/community.rs index 0ca4ac47a..18a4dc461 100644 --- a/crates/api/src/community.rs +++ b/crates/api/src/community.rs @@ -399,16 +399,14 @@ impl Perform for TransferCommunity { } // Mod tables - // TODO there should probably be another table for transfer community - // Right now, it will just look like it modded them twice - let form = ModAddCommunityForm { + let form = ModTransferCommunityForm { mod_person_id: local_user_view.person.id, other_person_id: data.person_id, community_id: data.community_id, removed: Some(false), }; blocking(context.pool(), move |conn| { - ModAddCommunity::create(conn, &form) + ModTransferCommunity::create(conn, &form) }) .await??; diff --git a/crates/api/src/site.rs b/crates/api/src/site.rs index d67c11815..7b6783a70 100644 --- a/crates/api/src/site.rs +++ b/crates/api/src/site.rs @@ -40,6 +40,7 @@ use lemmy_db_views_moderator::{ mod_remove_community_view::ModRemoveCommunityView, mod_remove_post_view::ModRemovePostView, mod_sticky_post_view::ModStickyPostView, + mod_transfer_community_view::ModTransferCommunityView, }; use lemmy_utils::{ location_info, @@ -97,6 +98,11 @@ impl Perform for GetModlog { }) .await??; + let transferred_to_community = blocking(context.pool(), move |conn| { + ModTransferCommunityView::list(conn, community_id, mod_person_id, page, limit) + }) + .await??; + // These arrays are only for the full modlog, when a community isn't given let (removed_communities, banned, added) = if data.community_id.is_none() { blocking(context.pool(), move |conn| { @@ -122,6 +128,7 @@ impl Perform for GetModlog { banned, added_to_community, added, + transferred_to_community, }) } } diff --git a/crates/api_common/src/site.rs b/crates/api_common/src/site.rs index e5c167f42..796549860 100644 --- a/crates/api_common/src/site.rs +++ b/crates/api_common/src/site.rs @@ -16,6 +16,7 @@ use lemmy_db_views_moderator::{ mod_remove_community_view::ModRemoveCommunityView, mod_remove_post_view::ModRemovePostView, mod_sticky_post_view::ModStickyPostView, + mod_transfer_community_view::ModTransferCommunityView, }; use serde::{Deserialize, Serialize}; @@ -60,6 +61,7 @@ pub struct GetModlogResponse { pub banned_from_community: Vec, pub banned: Vec, pub added_to_community: Vec, + pub transferred_to_community: Vec, pub added: Vec, } diff --git a/crates/db_queries/src/source/moderator.rs b/crates/db_queries/src/source/moderator.rs index 25ef1416d..eee5d5e9f 100644 --- a/crates/db_queries/src/source/moderator.rs +++ b/crates/db_queries/src/source/moderator.rs @@ -192,6 +192,33 @@ impl Crud for ModAddCommunity { } } +impl Crud for ModTransferCommunity { + type Form = ModTransferCommunityForm; + type IdType = i32; + fn read(conn: &PgConnection, from_id: i32) -> Result { + use lemmy_db_schema::schema::mod_transfer_community::dsl::*; + mod_transfer_community.find(from_id).first::(conn) + } + + fn create(conn: &PgConnection, form: &ModTransferCommunityForm) -> Result { + use lemmy_db_schema::schema::mod_transfer_community::dsl::*; + insert_into(mod_transfer_community) + .values(form) + .get_result::(conn) + } + + fn update( + conn: &PgConnection, + from_id: i32, + form: &ModTransferCommunityForm, + ) -> Result { + use lemmy_db_schema::schema::mod_transfer_community::dsl::*; + diesel::update(mod_transfer_community.find(from_id)) + .set(form) + .get_result::(conn) + } +} + impl Crud for ModAdd { type Form = ModAddForm; type IdType = i32; diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 8c17b0bd5..ad1ce2b35 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -181,6 +181,17 @@ table! { } } +table! { + mod_transfer_community (id) { + id -> Int4, + mod_person_id -> Int4, + other_person_id -> Int4, + community_id -> Int4, + removed -> Nullable, + when_ -> Timestamp, + } +} + table! { mod_ban (id) { id -> Int4, @@ -549,6 +560,7 @@ joinable!(community_person_ban -> community (community_id)); joinable!(community_person_ban -> person (person_id)); joinable!(local_user -> person (person_id)); joinable!(mod_add_community -> community (community_id)); +joinable!(mod_transfer_community -> community (community_id)); joinable!(mod_ban_from_community -> community (community_id)); joinable!(mod_lock_post -> person (mod_person_id)); joinable!(mod_lock_post -> post (post_id)); @@ -593,6 +605,7 @@ allow_tables_to_appear_in_same_query!( local_user, mod_add, mod_add_community, + mod_transfer_community, mod_ban, mod_ban_from_community, mod_lock_post, diff --git a/crates/db_schema/src/source/moderator.rs b/crates/db_schema/src/source/moderator.rs index 19580fb92..66889ae50 100644 --- a/crates/db_schema/src/source/moderator.rs +++ b/crates/db_schema/src/source/moderator.rs @@ -9,6 +9,7 @@ use crate::{ mod_remove_community, mod_remove_post, mod_sticky_post, + mod_transfer_community, }, CommentId, CommunityId, @@ -181,6 +182,26 @@ pub struct ModAddCommunityForm { pub removed: Option, } +#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] +#[table_name = "mod_transfer_community"] +pub struct ModTransferCommunity { + pub id: i32, + pub mod_person_id: PersonId, + pub other_person_id: PersonId, + pub community_id: CommunityId, + pub removed: Option, + pub when_: chrono::NaiveDateTime, +} + +#[derive(Insertable, AsChangeset)] +#[table_name = "mod_transfer_community"] +pub struct ModTransferCommunityForm { + pub mod_person_id: PersonId, + pub other_person_id: PersonId, + pub community_id: CommunityId, + pub removed: Option, +} + #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] #[table_name = "mod_add"] pub struct ModAdd { diff --git a/crates/db_views_moderator/src/lib.rs b/crates/db_views_moderator/src/lib.rs index 827dd1447..354504c4a 100644 --- a/crates/db_views_moderator/src/lib.rs +++ b/crates/db_views_moderator/src/lib.rs @@ -7,3 +7,4 @@ pub mod mod_remove_comment_view; pub mod mod_remove_community_view; pub mod mod_remove_post_view; pub mod mod_sticky_post_view; +pub mod mod_transfer_community_view; diff --git a/crates/db_views_moderator/src/mod_transfer_community_view.rs b/crates/db_views_moderator/src/mod_transfer_community_view.rs new file mode 100644 index 000000000..94c0abc7d --- /dev/null +++ b/crates/db_views_moderator/src/mod_transfer_community_view.rs @@ -0,0 +1,85 @@ +use diesel::{result::Error, *}; +use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec}; +use lemmy_db_schema::{ + schema::{community, mod_transfer_community, person, person_alias_1}, + source::{ + community::{Community, CommunitySafe}, + moderator::ModTransferCommunity, + person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1}, + }, + CommunityId, + PersonId, +}; +use serde::Serialize; + +#[derive(Debug, Serialize, Clone)] +pub struct ModTransferCommunityView { + pub mod_transfer_community: ModTransferCommunity, + pub moderator: PersonSafe, + pub community: CommunitySafe, + pub modded_person: PersonSafeAlias1, +} + +type ModTransferCommunityViewTuple = ( + ModTransferCommunity, + PersonSafe, + CommunitySafe, + PersonSafeAlias1, +); + +impl ModTransferCommunityView { + pub fn list( + conn: &PgConnection, + community_id: Option, + mod_person_id: Option, + page: Option, + limit: Option, + ) -> Result, Error> { + let mut query = mod_transfer_community::table + .inner_join(person::table.on(mod_transfer_community::mod_person_id.eq(person::id))) + .inner_join(community::table) + .inner_join( + person_alias_1::table.on(mod_transfer_community::other_person_id.eq(person_alias_1::id)), + ) + .select(( + mod_transfer_community::all_columns, + Person::safe_columns_tuple(), + Community::safe_columns_tuple(), + PersonAlias1::safe_columns_tuple(), + )) + .into_boxed(); + + if let Some(mod_person_id) = mod_person_id { + query = query.filter(mod_transfer_community::mod_person_id.eq(mod_person_id)); + }; + + if let Some(community_id) = community_id { + query = query.filter(mod_transfer_community::community_id.eq(community_id)); + }; + + let (limit, offset) = limit_and_offset(page, limit); + + let res = query + .limit(limit) + .offset(offset) + .order_by(mod_transfer_community::when_.desc()) + .load::(conn)?; + + Ok(Self::from_tuple_to_vec(res)) + } +} + +impl ViewToVec for ModTransferCommunityView { + type DbTuple = ModTransferCommunityViewTuple; + fn from_tuple_to_vec(items: Vec) -> Vec { + items + .iter() + .map(|a| Self { + mod_transfer_community: a.0.to_owned(), + moderator: a.1.to_owned(), + community: a.2.to_owned(), + modded_person: a.3.to_owned(), + }) + .collect::>() + } +} diff --git a/migrations/2021-08-17-210508_create_mod_transfer_community/down.sql b/migrations/2021-08-17-210508_create_mod_transfer_community/down.sql new file mode 100644 index 000000000..8a2d8820a --- /dev/null +++ b/migrations/2021-08-17-210508_create_mod_transfer_community/down.sql @@ -0,0 +1 @@ +drop table mod_transfer_community; diff --git a/migrations/2021-08-17-210508_create_mod_transfer_community/up.sql b/migrations/2021-08-17-210508_create_mod_transfer_community/up.sql new file mode 100644 index 000000000..b43cf1408 --- /dev/null +++ b/migrations/2021-08-17-210508_create_mod_transfer_community/up.sql @@ -0,0 +1,9 @@ +-- Add the mod_transfer_community log table +create table mod_transfer_community ( + id serial primary key, + mod_person_id int references person on update cascade on delete cascade not null, + other_person_id int references person on update cascade on delete cascade not null, + community_id int references community on update cascade on delete cascade not null, + removed boolean default false, + when_ timestamp not null default now() +); From b241bb9cb7a707da363e0605fa6dd005dc6d2285 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Tue, 17 Aug 2021 19:16:20 -0400 Subject: [PATCH 8/9] Adding script to upgrade deps, and check for unused ones. --- scripts/upgrade_deps.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100755 scripts/upgrade_deps.sh diff --git a/scripts/upgrade_deps.sh b/scripts/upgrade_deps.sh new file mode 100755 index 000000000..90adb896f --- /dev/null +++ b/scripts/upgrade_deps.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +pushd ../ + +# Check unused deps +cargo udeps --all-targets + +# Upgrade deps +cargo upgrade --workspace + +# Run check +cargo check + +popd From 6af75492a94606a5c8e771e6150c095352532ee9 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 19 Aug 2021 10:12:49 -0400 Subject: [PATCH 9/9] Swap out iframely (#1706) * Replace Iframely. Fixes #1681 * Add post_link_tags to nginx * Adding post_link_tags route * Cleaning up post_link_tags * Changing PostLink to SiteMetadata, adding it to the API. * Fixing issue when local has no openssl certs. * Fixing an issue with pictrs errors * Revert "Fixing issue when local has no openssl certs." This reverts commit dbf7d1b1ee03846e5ef7b7156e618424f1150e1d. * Add ca-certs to dockerfile for volume mount. * Cleaning up fetch_pictrs request * Changing to fetch_site_data --- Cargo.lock | 537 +++++++++++++++++++++------ README.md | 1 - ansible/lemmy.yml | 4 - ansible/lemmy_dev.yml | 4 - ansible/templates/docker-compose.yml | 10 - ansible/templates/nginx.conf | 6 - config/config.hjson | 2 - crates/api/src/lib.rs | 3 + crates/api/src/post.rs | 19 +- crates/api_common/src/post.rs | 11 + crates/api_crud/src/post/create.rs | 9 +- crates/api_crud/src/post/update.rs | 9 +- crates/apub/src/objects/post.rs | 8 +- crates/utils/Cargo.toml | 1 + crates/utils/src/request.rs | 142 +++++-- crates/utils/src/settings/structs.rs | 2 - crates/websocket/src/lib.rs | 1 + docker/dev/docker-compose.yml | 10 - docker/dev/volume_mount.dockerfile | 2 +- docker/federation/docker-compose.yml | 7 - docker/federation/nginx.conf | 30 -- docker/iframely.config.local.js | 283 -------------- docker/lemmy.hjson | 2 + docker/prod/docker-compose.yml | 9 - src/api_routes.rs | 6 +- src/main.rs | 1 + 26 files changed, 588 insertions(+), 531 deletions(-) delete mode 100644 docker/iframely.config.local.js diff --git a/Cargo.lock b/Cargo.lock index d859f2745..4cdcc47f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,16 +58,16 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.0.0-beta.8" +version = "3.0.0-beta.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cd16d6b846983ffabfd081e1a67abd7698094fcbe7b3d9bcf1acbc6f546a516" +checksum = "01260589f1aafad11224002741eb37bc603b4ce55b4e3556d2b2122f9aac7c51" dependencies = [ "actix-codec", "actix-rt", "actix-service", "actix-tls", "actix-utils", - "ahash 0.7.4", + "ahash", "base64 0.13.0", "bitflags", "bytes", @@ -91,7 +91,7 @@ dependencies = [ "rand 0.8.4", "regex", "serde", - "sha-1 0.9.6", + "sha-1 0.9.7", "smallvec", "time 0.2.27", "tokio", @@ -204,7 +204,7 @@ dependencies = [ "actix-tls", "actix-utils", "actix-web-codegen", - "ahash 0.7.4", + "ahash", "bytes", "cfg-if", "cookie", @@ -281,12 +281,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" -[[package]] -name = "ahash" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" - [[package]] name = "ahash" version = "0.7.4" @@ -356,6 +350,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "autocfg" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" + [[package]] name = "autocfg" version = "1.0.1" @@ -469,9 +469,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitvec" @@ -540,9 +540,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytemuck" -version = "1.7.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9966d2ab714d0f785dbac0a0396251a35280aeb42413281617d0209ab4898435" +checksum = "72957246c41db82b8ef88a5486143830adeb8227ef9837740bdec67724cf2c5b" [[package]] name = "byteorder" @@ -587,9 +587,9 @@ checksum = "7b02b629252fe8ef6460461409564e2c21d0c8e77e0944f3d189ff06c4e932ad" [[package]] name = "cc" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" +checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" [[package]] name = "cfg-if" @@ -629,6 +629,15 @@ dependencies = [ "chrono", ] +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -722,9 +731,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -861,13 +870,14 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.14" +version = "0.99.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc7b9cef1e351660e5443924e4f43ab25fbbed3e9a5f052df3677deb4d6b320" +checksum = "40eebddd2156ce1bb37b20bbe5151340a31828b1f2d22ba4141f3531710e38df" dependencies = [ "convert_case", "proc-macro2 1.0.28", "quote 1.0.9", + "rustc_version 0.3.3", "syn 1.0.74", ] @@ -1015,18 +1025,18 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "fallible_collections" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad9169582543d2cfe9961be1e9eaf4fc42f9aa3483f7c485717b8dde36466ea" +checksum = "eaefd4190151d458f16f0793d3452d7f13aeb3701566a4cefc4c37598876cc00" dependencies = [ - "hashbrown 0.9.1", + "hashbrown", ] [[package]] name = "fastrand" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77b705829d1e87f762c2df6da140b26af5839e1033aa84aa5f56bb688e4e1bdb" +checksum = "b394ed3d285a429378d3b384b9eb1285267e7df4b166df24b7a6939a04dc392e" dependencies = [ "instant", ] @@ -1074,12 +1084,28 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "funty" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" +[[package]] +name = "futf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b" +dependencies = [ + "mac", + "new_debug_unreachable", +] + [[package]] name = "futures" version = "0.3.16" @@ -1134,7 +1160,7 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57" dependencies = [ - "autocfg", + "autocfg 1.0.1", "proc-macro-hack", "proc-macro2 1.0.28", "quote 1.0.9", @@ -1159,7 +1185,7 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78" dependencies = [ - "autocfg", + "autocfg 1.0.1", "futures-channel", "futures-core", "futures-io", @@ -1250,20 +1276,14 @@ dependencies = [ "tracing", ] -[[package]] -name = "hashbrown" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" -dependencies = [ - "ahash 0.4.7", -] - [[package]] name = "hashbrown" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] [[package]] name = "heck" @@ -1300,6 +1320,20 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549" +[[package]] +name = "html5ever" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c213fa6a618dc1da552f54f85cba74b05d8e883c92ec4e89067736938084c26e" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", +] + [[package]] name = "http" version = "0.2.4" @@ -1313,9 +1347,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60daa14be0e0786db0f03a9e57cb404c9d756eed2b6c62b9ea98ec5743ec75a9" +checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5" dependencies = [ "bytes", "http", @@ -1387,9 +1421,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.9" +version = "0.14.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07d6baa1b441335f3ce5098ac421fb6547c46dda735ca1bc6d0153c838f9dd83" +checksum = "0b61cf2d1aebcf6e6352c97b81dc2244ca29194be1b276f5d8ad5c6330fffb11" dependencies = [ "bytes", "futures-channel", @@ -1464,15 +1498,15 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" dependencies = [ - "autocfg", - "hashbrown 0.11.2", + "autocfg 1.0.1", + "hashbrown", ] [[package]] name = "instant" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" dependencies = [ "cfg-if", ] @@ -1509,9 +1543,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.51" +version = "0.3.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" +checksum = "ce791b7ca6638aae45be056e068fc756d871eb3b3b10b8efa62d1c9cec616752" dependencies = [ "wasm-bindgen", ] @@ -1885,6 +1919,7 @@ dependencies = [ "thiserror", "tokio", "url", + "webpage", ] [[package]] @@ -1936,9 +1971,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" +checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765" [[package]] name = "local-channel" @@ -1988,12 +2023,34 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + [[package]] name = "maplit" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" +[[package]] +name = "markup5ever" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897636f9850c3eef4905a5540683ed53dc9393860f0846cab2c2ddf9939862ff" +dependencies = [ + "phf", + "phf_codegen", + "serde", + "serde_derive", + "serde_json", + "string_cache", + "string_cache_codegen", + "tendril", +] + [[package]] name = "match_cfg" version = "0.1.0" @@ -2002,15 +2059,15 @@ checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" [[package]] name = "matches" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "memchr" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memoffset" @@ -2018,7 +2075,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" dependencies = [ - "autocfg", + "autocfg 1.0.1", ] [[package]] @@ -2064,7 +2121,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" dependencies = [ "adler", - "autocfg", + "autocfg 1.0.1", ] [[package]] @@ -2091,9 +2148,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4" +checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" dependencies = [ "lazy_static", "libc", @@ -2107,6 +2164,12 @@ dependencies = [ "tempfile", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + [[package]] name = "nom" version = "6.1.2" @@ -2134,7 +2197,7 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" dependencies = [ - "autocfg", + "autocfg 1.0.1", "num-integer", "num-traits", ] @@ -2145,7 +2208,7 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" dependencies = [ - "autocfg", + "autocfg 1.0.1", "num-traits", ] @@ -2155,7 +2218,7 @@ version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" dependencies = [ - "autocfg", + "autocfg 1.0.1", "num-integer", "num-traits", ] @@ -2166,7 +2229,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" dependencies = [ - "autocfg", + "autocfg 1.0.1", "num-integer", "num-traits", ] @@ -2177,7 +2240,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ - "autocfg", + "autocfg 1.0.1", ] [[package]] @@ -2234,7 +2297,7 @@ version = "0.9.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1996d2d305e561b70d1ee0c53f1542833f4e1ac6ce9a6708b6ff2738ca67dc82" dependencies = [ - "autocfg", + "autocfg 1.0.1", "cc", "libc", "pkg-config", @@ -2333,19 +2396,57 @@ dependencies = [ ] [[package]] -name = "pin-project" -version = "1.0.7" +name = "phf" +version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4" +checksum = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" +dependencies = [ + "phf_shared", + "rand 0.6.5", +] + +[[package]] +name = "phf_shared" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f" +checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" dependencies = [ "proc-macro2 1.0.28", "quote 1.0.9", @@ -2397,6 +2498,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -2478,6 +2585,25 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +dependencies = [ + "autocfg 0.1.7", + "libc", + "rand_chacha 0.1.1", + "rand_core 0.4.2", + "rand_hc 0.1.0", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi", +] + [[package]] name = "rand" version = "0.7.3" @@ -2503,6 +2629,16 @@ dependencies = [ "rand_hc 0.3.1", ] +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +dependencies = [ + "autocfg 0.1.7", + "rand_core 0.3.1", +] + [[package]] name = "rand_chacha" version = "0.2.2" @@ -2523,6 +2659,21 @@ dependencies = [ "rand_core 0.6.3", ] +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + [[package]] name = "rand_core" version = "0.5.1" @@ -2541,6 +2692,15 @@ dependencies = [ "getrandom 0.2.3", ] +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "rand_hc" version = "0.2.0" @@ -2559,13 +2719,66 @@ dependencies = [ "rand_core 0.6.3", ] +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +dependencies = [ + "libc", + "rand_core 0.4.2", + "winapi", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +dependencies = [ + "autocfg 0.1.7", + "rand_core 0.4.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "rayon" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" dependencies = [ - "autocfg", + "autocfg 1.0.1", "crossbeam-deque", "either", "rayon-core", @@ -2585,10 +2798,19 @@ dependencies = [ ] [[package]] -name = "redox_syscall" -version = "0.2.9" +name = "rdrand" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" dependencies = [ "bitflags", ] @@ -2695,7 +2917,16 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver", + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", ] [[package]] @@ -2793,7 +3024,16 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ - "semver-parser", + "semver-parser 0.7.0", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser 0.10.2", ] [[package]] @@ -2802,6 +3042,15 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + [[package]] name = "serde" version = "1.0.127" @@ -2905,9 +3154,9 @@ dependencies = [ [[package]] name = "sha-1" -version = "0.9.6" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c4cfa741c5832d0ef7fab46cabed29c2aae926db0b11bb2069edd8db5e64e16" +checksum = "1a0c8611594e2ab4ebbf06ec7cbbf0a99450b8570e96cbf5188b5d5f6ef18d81" dependencies = [ "block-buffer 0.9.0", "cfg-if", @@ -2962,10 +3211,16 @@ dependencies = [ ] [[package]] -name = "slab" -version = "0.4.3" +name = "siphasher" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" +checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" + +[[package]] +name = "slab" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590" [[package]] name = "smallvec" @@ -2986,9 +3241,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2" +checksum = "765f090f0e423d2b55843402a07915add955e7d60657db13707a159727326cad" dependencies = [ "libc", "winapi", @@ -3016,7 +3271,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" dependencies = [ "discard", - "rustc_version", + "rustc_version 0.2.3", "stdweb-derive", "stdweb-internal-macros", "stdweb-internal-runtime", @@ -3058,6 +3313,40 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" +[[package]] +name = "string_cache" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89c058a82f9fd69b1becf8c274f412281038877c553182f1d02eb027045a2d67" +dependencies = [ + "lazy_static", + "new_debug_unreachable", + "phf_shared", + "precomputed-hash", + "serde", + "string_cache_codegen", + "string_cache_shared", +] + +[[package]] +name = "string_cache_codegen" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f45ed1b65bf9a4bf2f7b7dc59212d1926e9eaf00fa998988e420fd124467c6" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2 1.0.28", + "quote 1.0.9", + "string_cache_shared", +] + +[[package]] +name = "string_cache_shared" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" + [[package]] name = "strsim" version = "0.9.3" @@ -3099,6 +3388,17 @@ dependencies = [ "unicode-xid 0.1.0", ] +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", +] + [[package]] name = "syn" version = "1.0.74" @@ -3130,6 +3430,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "tendril" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9ef557cb397a4f0a5a3a628f06515f78563f2209e64d47055d9dc6052bf5e33" +dependencies = [ + "futf", + "mac", + "utf-8", +] + [[package]] name = "termcolor" version = "1.1.2" @@ -3221,9 +3532,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" +checksum = "848a1e1181b9f6753b5e96a092749e29b11d19ede67dfbbd6c7dc7e0f49b5338" dependencies = [ "tinyvec_macros", ] @@ -3240,7 +3551,7 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01cf844b23c6131f624accf65ce0e4e9956a8bb329400ea5bcc26ae3a5c20b0b" dependencies = [ - "autocfg", + "autocfg 1.0.1", "bytes", "libc", "memchr", @@ -3315,9 +3626,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052" +checksum = "2ca517f43f0fb96e0c3072ed5c275fe5eece87e8cb52f4a77b69226d3b1c9df8" dependencies = [ "lazy_static", ] @@ -3379,12 +3690,9 @@ checksum = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c" [[package]] name = "unicode-bidi" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" -dependencies = [ - "matches", -] +checksum = "246f4c42e67e7a4e3c6106ff716a5d067d4132a642840b242e357e468a2a0085" [[package]] name = "unicode-normalization" @@ -3438,6 +3746,12 @@ dependencies = [ "serde", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "uuid" version = "0.8.2" @@ -3484,9 +3798,9 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" -version = "0.2.74" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" +checksum = "b608ecc8f4198fe8680e2ed18eccab5f0cd4caaf3d83516fa5fb2e927fda2586" dependencies = [ "cfg-if", "serde", @@ -3496,9 +3810,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.74" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" +checksum = "580aa3a91a63d23aac5b6b267e2d13cb4f363e31dce6c352fca4752ae12e479f" dependencies = [ "bumpalo", "lazy_static", @@ -3511,9 +3825,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.24" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fba7978c679d53ce2d0ac80c8c175840feb849a161664365d1287b41f2e67f1" +checksum = "16646b21c3add8e13fdb8f20172f8a28c3dbf62f45406bcff0233188226cfe0c" dependencies = [ "cfg-if", "js-sys", @@ -3523,9 +3837,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.74" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" +checksum = "171ebf0ed9e1458810dfcb31f2e766ad6b3a89dbda42d8901f2b268277e5f09c" dependencies = [ "quote 1.0.9", "wasm-bindgen-macro-support", @@ -3533,9 +3847,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.74" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" +checksum = "6c2657dd393f03aa2a659c25c6ae18a13a4048cebd220e147933ea837efc589f" dependencies = [ "proc-macro2 1.0.28", "quote 1.0.9", @@ -3546,20 +3860,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.74" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" +checksum = "2e0c4a743a309662d45f4ede961d7afa4ba4131a59a639f29b0069c3798bbcc2" [[package]] name = "web-sys" -version = "0.3.51" +version = "0.3.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582" +checksum = "01c70a82d842c9979078c772d4a1344685045f1a5628f677c2b2eab4dd7d2696" dependencies = [ "js-sys", "wasm-bindgen", ] +[[package]] +name = "webpage" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adf8232428a373fe9dc80dc3b7ba15c35621746691869ae2aa4fe0bb6f01098" +dependencies = [ + "html5ever", + "serde", + "serde_json", +] + [[package]] name = "webpki" version = "0.21.4" diff --git a/README.md b/README.md index 0a08c61ce..ade81cbf6 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,6 @@ Each Lemmy server can set its own moderation policy; appointing site-wide admins - Can transfer site and communities to others. - Can fully erase your data, replacing all posts and comments. - NSFW post / community support. -- OEmbed support via Iframely. - High performance. - Server is written in rust. - Front end is `~80kB` gzipped. diff --git a/ansible/lemmy.yml b/ansible/lemmy.yml index 969d6aff2..91bda5715 100644 --- a/ansible/lemmy.yml +++ b/ansible/lemmy.yml @@ -72,16 +72,12 @@ - src: 'templates/nginx.conf' dest: '/etc/nginx/sites-enabled/lemmy.conf' mode: '0644' - - src: '../docker/iframely.config.local.js' - dest: '{{lemmy_base_dir}}/iframely.config.local.js' - mode: '0600' vars: lemmy_docker_image: "dessalines/lemmy:{{ lookup('file', 'VERSION') }}" lemmy_docker_ui_image: "dessalines/lemmy-ui:{{ lookup('file', 'VERSION') }}" lemmy_port: "8536" lemmy_ui_port: "1235" pictshare_port: "8537" - iframely_port: "8538" - name: add config file (only during initial setup) template: diff --git a/ansible/lemmy_dev.yml b/ansible/lemmy_dev.yml index 141900a35..a685cbe3e 100644 --- a/ansible/lemmy_dev.yml +++ b/ansible/lemmy_dev.yml @@ -61,16 +61,12 @@ - src: 'templates/nginx.conf' dest: '/etc/nginx/sites-enabled/lemmy.conf' mode: '0644' - - src: '../docker/iframely.config.local.js' - dest: '{{lemmy_base_dir}}/iframely.config.local.js' - mode: '0600' vars: lemmy_docker_image: "dessalines/lemmy:dev" lemmy_docker_ui_image: "dessalines/lemmy-ui:{{ lookup('file', 'VERSION') }}" lemmy_port: "8536" lemmy_ui_port: "1235" pictshare_port: "8537" - iframely_port: "8538" postgres_password: "{{ lookup('password', 'passwords/{{ inventory_hostname }}/postgres chars=ascii_letters,digits') }}" - name: add config file (only during initial setup) diff --git a/ansible/templates/docker-compose.yml b/ansible/templates/docker-compose.yml index 1d2609e63..5b04c28d4 100644 --- a/ansible/templates/docker-compose.yml +++ b/ansible/templates/docker-compose.yml @@ -13,7 +13,6 @@ services: depends_on: - postgres - pictrs - - iframely lemmy-ui: image: {{ lemmy_docker_ui_image }} @@ -47,15 +46,6 @@ services: restart: always mem_limit: 200m - iframely: - image: dogbin/iframely:latest - ports: - - "127.0.0.1:8061:80" - volumes: - - ./iframely.config.local.js:/iframely/config.local.js:ro - restart: always - mem_limit: 200m - postfix: image: mwader/postfix-relay environment: diff --git a/ansible/templates/nginx.conf b/ansible/templates/nginx.conf index 9c9244426..132821c76 100644 --- a/ansible/templates/nginx.conf +++ b/ansible/templates/nginx.conf @@ -101,12 +101,6 @@ server { return 301 /pictrs/image/$1; } - location /iframely/ { - proxy_pass http://0.0.0.0:8061/; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } } # Anonymize IP addresses diff --git a/config/config.hjson b/config/config.hjson index 236751f4e..cb08dda45 100644 --- a/config/config.hjson +++ b/config/config.hjson @@ -37,8 +37,6 @@ jwt_secret: "changeme" # address where pictrs is available pictrs_url: "http://pictrs:8080" - # address where iframely is available - iframely_url: "http://iframely" # maximum length of local community and user names actor_name_max_length: 20 # rate limits for various user actions, by user ip diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index 6234e7565..1c194b311 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -121,6 +121,9 @@ pub async fn match_websocket_operation( UserOperation::ResolvePostReport => { do_websocket_operation::(context, id, op, data).await } + UserOperation::GetSiteMetadata => { + do_websocket_operation::(context, id, op, data).await + } // Comment ops UserOperation::MarkCommentAsRead => { diff --git a/crates/api/src/post.rs b/crates/api/src/post.rs index 3de027313..1cb6c587e 100644 --- a/crates/api/src/post.rs +++ b/crates/api/src/post.rs @@ -23,7 +23,7 @@ use lemmy_apub::{ use lemmy_db_queries::{source::post::Post_, Crud, Likeable, Saveable}; use lemmy_db_schema::source::{moderator::*, post::*}; use lemmy_db_views::post_view::PostView; -use lemmy_utils::{ApiError, ConnectionId, LemmyError}; +use lemmy_utils::{request::fetch_site_metadata, ApiError, ConnectionId, LemmyError}; use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperation}; use std::convert::TryInto; @@ -285,3 +285,20 @@ impl Perform for SavePost { Ok(PostResponse { post_view }) } } + +#[async_trait::async_trait(?Send)] +impl Perform for GetSiteMetadata { + type Response = GetSiteMetadataResponse; + + async fn perform( + &self, + context: &Data, + _websocket_id: Option, + ) -> Result { + let data: &Self = self; + + let metadata = fetch_site_metadata(context.client(), &data.url).await?; + + Ok(GetSiteMetadataResponse { metadata }) + } +} diff --git a/crates/api_common/src/post.rs b/crates/api_common/src/post.rs index bb6b36249..5a83a0c50 100644 --- a/crates/api_common/src/post.rs +++ b/crates/api_common/src/post.rs @@ -8,6 +8,7 @@ use lemmy_db_views_actor::{ community_moderator_view::CommunityModeratorView, community_view::CommunityView, }; +use lemmy_utils::request::SiteMetadata; use serde::{Deserialize, Serialize}; use url::Url; @@ -148,3 +149,13 @@ pub struct ListPostReports { pub struct ListPostReportsResponse { pub posts: Vec, } + +#[derive(Deserialize, Debug)] +pub struct GetSiteMetadata { + pub url: Url, +} + +#[derive(Serialize, Clone, Debug)] +pub struct GetSiteMetadataResponse { + pub metadata: SiteMetadata, +} diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 28c739689..547c657cf 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -20,7 +20,7 @@ use lemmy_apub::{ use lemmy_db_queries::{source::post::Post_, Crud, Likeable}; use lemmy_db_schema::source::post::*; use lemmy_utils::{ - request::fetch_iframely_and_pictrs_data, + request::fetch_site_data, utils::{check_slurs, check_slurs_opt, clean_url_params, is_valid_post_title}, ApiError, ConnectionId, @@ -49,11 +49,10 @@ impl PerformCrud for CreatePost { check_community_ban(local_user_view.person.id, data.community_id, context.pool()).await?; - // Fetch Iframely and pictrs cached image + // Fetch post links and pictrs cached image let data_url = data.url.as_ref(); - let (iframely_response, pictrs_thumbnail) = - fetch_iframely_and_pictrs_data(context.client(), data_url).await?; - let (embed_title, embed_description, embed_html) = iframely_response + let (metadata_res, pictrs_thumbnail) = fetch_site_data(context.client(), data_url).await; + let (embed_title, embed_description, embed_html) = metadata_res .map(|u| (u.title, u.description, u.html)) .unwrap_or((None, None, None)); diff --git a/crates/api_crud/src/post/update.rs b/crates/api_crud/src/post/update.rs index 4b63ebd2c..d52538e06 100644 --- a/crates/api_crud/src/post/update.rs +++ b/crates/api_crud/src/post/update.rs @@ -5,7 +5,7 @@ use lemmy_apub::activities::{post::create_or_update::CreateOrUpdatePost, CreateO use lemmy_db_queries::{source::post::Post_, Crud}; use lemmy_db_schema::{naive_now, source::post::*}; use lemmy_utils::{ - request::fetch_iframely_and_pictrs_data, + request::fetch_site_data, utils::{check_slurs_opt, clean_url_params, is_valid_post_title}, ApiError, ConnectionId, @@ -49,11 +49,10 @@ impl PerformCrud for EditPost { return Err(ApiError::err("no_post_edit_allowed").into()); } - // Fetch Iframely and Pictrs cached image + // Fetch post links and Pictrs cached image let data_url = data.url.as_ref(); - let (iframely_response, pictrs_thumbnail) = - fetch_iframely_and_pictrs_data(context.client(), data_url).await?; - let (embed_title, embed_description, embed_html) = iframely_response + let (metadata_res, pictrs_thumbnail) = fetch_site_data(context.client(), data_url).await; + let (embed_title, embed_description, embed_html) = metadata_res .map(|u| (u.title, u.description, u.html)) .unwrap_or((None, None, None)); diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index 43a019d16..4773f8c56 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -31,7 +31,7 @@ use lemmy_db_schema::{ }, }; use lemmy_utils::{ - request::fetch_iframely_and_pictrs_data, + request::fetch_site_data, utils::{check_slurs, convert_datetime, markdown_to_html, remove_slurs}, LemmyError, }; @@ -188,12 +188,12 @@ impl FromApub for Post { let community = extract_community(&page.to, context, request_counter).await?; let thumbnail_url: Option = page.image.clone().map(|i| i.url); - let (iframely_response, pictrs_thumbnail) = if let Some(url) = &page.url { - fetch_iframely_and_pictrs_data(context.client(), Some(url)).await? + let (metadata_res, pictrs_thumbnail) = if let Some(url) = &page.url { + fetch_site_data(context.client(), Some(url)).await } else { (None, thumbnail_url) }; - let (embed_title, embed_description, embed_html) = iframely_response + let (embed_title, embed_description, embed_html) = metadata_res .map(|u| (u.title, u.description, u.html)) .unwrap_or((None, None, None)); diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml index 018ed52c9..c46a4e0cf 100644 --- a/crates/utils/Cargo.toml +++ b/crates/utils/Cargo.toml @@ -38,3 +38,4 @@ http = "0.2.4" jsonwebtoken = "7.2.0" deser-hjson = "1.0.2" smart-default = "0.6.0" +webpage = { version = "1.1", default-features = false, features = ["serde"] } diff --git a/crates/utils/src/request.rs b/crates/utils/src/request.rs index c59180c55..a881cf02c 100644 --- a/crates/utils/src/request.rs +++ b/crates/utils/src/request.rs @@ -3,10 +3,11 @@ use anyhow::anyhow; use log::error; use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; use reqwest::Client; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use std::future::Future; use thiserror::Error; use url::Url; +use webpage::HTML; #[derive(Clone, Debug, Error)] #[error("Error sending request, {0}")] @@ -47,31 +48,61 @@ where response.expect("retry http request") } -#[derive(Deserialize, Debug)] -pub struct IframelyResponse { +#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)] +pub struct SiteMetadata { pub title: Option, pub description: Option, - thumbnail_url: Option, + image: Option, pub html: Option, } -pub(crate) async fn fetch_iframely( - client: &Client, - url: &Url, -) -> Result { - if let Some(iframely_url) = Settings::get().iframely_url { - let fetch_url = format!("{}/oembed?url={}", iframely_url, url); +/// Fetches the post link html tags (like title, description, image, etc) +pub async fn fetch_site_metadata(client: &Client, url: &Url) -> Result { + let response = retry(|| client.get(url.as_str()).send()).await?; - let response = retry(|| client.get(&fetch_url).send()).await?; + let html = response + .text() + .await + .map_err(|e| RecvError(e.to_string()))?; - let res: IframelyResponse = response - .json() - .await - .map_err(|e| RecvError(e.to_string()))?; - Ok(res) - } else { - Err(anyhow!("Missing Iframely URL in config.").into()) - } + let tags = html_to_site_metadata(&html)?; + + Ok(tags) +} + +fn html_to_site_metadata(html: &str) -> Result { + let page = HTML::from_string(html.to_string(), None)?; + + let page_title = page.title; + let page_description = page.description; + + let og_description = page + .opengraph + .properties + .get("description") + .map(|t| t.to_string()); + let og_title = page + .opengraph + .properties + .get("title") + .map(|t| t.to_string()); + let og_image = page + .opengraph + .images + .get(0) + .map(|ogo| Url::parse(&ogo.url).ok()) + .flatten(); + + let title = og_title.or(page_title); + let description = og_description.or(page_description); + let image = og_image; + + Ok(SiteMetadata { + title, + description, + image, + html: None, + }) } #[derive(Deserialize, Debug, Clone)] @@ -89,7 +120,7 @@ pub(crate) struct PictrsFile { pub(crate) async fn fetch_pictrs( client: &Client, image_url: &Url, -) -> Result, LemmyError> { +) -> Result { if let Some(pictrs_url) = Settings::get().pictrs_url { is_image_content_type(client, image_url).await?; @@ -107,37 +138,44 @@ pub(crate) async fn fetch_pictrs( .map_err(|e| RecvError(e.to_string()))?; if response.msg == "ok" { - Ok(Some(response)) + Ok(response) } else { Err(anyhow!("{}", &response.msg).into()) } } else { - Ok(None) + Err(anyhow!("pictrs_url not set up in config").into()) } } -pub async fn fetch_iframely_and_pictrs_data( +/// Both are options, since the URL might be either an html page, or an image +/// Returns the SiteMetadata, and a Pictrs URL, if there is a picture associated +pub async fn fetch_site_data( client: &Client, url: Option<&Url>, -) -> Result<(Option, Option), LemmyError> { +) -> (Option, Option) { match &url { Some(url) => { - // Fetch iframely data - let iframely_res_option = fetch_iframely(client, url).await.ok(); + // Fetch metadata + // Ignore errors, since it may be an image, or not have the data. + // Warning, this may ignore SSL errors + let metadata_option = fetch_site_metadata(client, url).await.ok(); // Fetch pictrs thumbnail - let pictrs_hash = match &iframely_res_option { - Some(iframely_res) => match &iframely_res.thumbnail_url { - Some(iframely_thumbnail_url) => fetch_pictrs(client, iframely_thumbnail_url) - .await? + let pictrs_hash = match &metadata_option { + Some(metadata_res) => match &metadata_res.image { + // Metadata, with image + // Try to generate a small thumbnail if there's a full sized one from post-links + Some(metadata_image) => fetch_pictrs(client, metadata_image) + .await .map(|r| r.files[0].file.to_owned()), - // Try to generate a small thumbnail if iframely is not supported + // Metadata, but no image None => fetch_pictrs(client, url) - .await? + .await .map(|r| r.files[0].file.to_owned()), }, + // No metadata, try to fetch the URL as an image None => fetch_pictrs(client, url) - .await? + .await .map(|r| r.files[0].file.to_owned()), }; @@ -151,11 +189,12 @@ pub async fn fetch_iframely_and_pictrs_data( )) .ok() }) + .ok() .flatten(); - Ok((iframely_res_option, pictrs_thumbnail)) + (metadata_option, pictrs_thumbnail) } - None => Ok((None, None)), + None => (None, None), } } @@ -176,12 +215,35 @@ async fn is_image_content_type(client: &Client, test: &Url) -> Result<(), LemmyE #[cfg(test)] mod tests { + use crate::request::fetch_site_metadata; + use url::Url; + + use super::SiteMetadata; + // These helped with testing - // #[test] - // fn test_iframely() { - // let res = fetch_iframely(client, "https://www.redspark.nu/?p=15341").await; - // assert!(res.is_ok()); - // } + #[actix_rt::test] + async fn test_site_metadata() { + let client = reqwest::Client::default(); + let sample_url = Url::parse("https://www.redspark.nu/en/peoples-war/district-leader-of-chand-led-cpn-arrested-in-bhojpur/").unwrap(); + let sample_res = fetch_site_metadata(&client, &sample_url).await.unwrap(); + assert_eq!( + SiteMetadata { + title: Some("District Leader Of Chand Led CPN Arrested In Bhojpur - Redspark".to_string()), + description: Some("BHOJPUR: A district leader of the outlawed Netra Bikram Chand alias Biplav-led outfit has been arrested. According to District Police".to_string()), + image: Some(Url::parse("https://www.redspark.nu/wp-content/uploads/2020/03/netra-bikram-chand-attends-program-1272019033653-1000x0-845x653-1.jpg").unwrap()), + html: None, + }, sample_res); + + let youtube_url = Url::parse("https://www.youtube.com/watch?v=IquO_TcMZIQ").unwrap(); + let youtube_res = fetch_site_metadata(&client, &youtube_url).await.unwrap(); + assert_eq!( + SiteMetadata { + title: Some("A Hard Look at Rent and Rent Seeking with Michael Hudson & Pepe Escobar".to_string()), + description: Some("An interactive discussion on wealth inequality and the “Great Game” on the control of natural resources.In this webinar organized jointly by the Henry George...".to_string()), + image: Some(Url::parse("https://i.ytimg.com/vi/IquO_TcMZIQ/maxresdefault.jpg").unwrap()), + html: None, + }, youtube_res); + } // #[test] // fn test_pictshare() { diff --git a/crates/utils/src/settings/structs.rs b/crates/utils/src/settings/structs.rs index 46dde9192..c9537fe36 100644 --- a/crates/utils/src/settings/structs.rs +++ b/crates/utils/src/settings/structs.rs @@ -29,8 +29,6 @@ pub struct Settings { #[default(None)] pub pictrs_url: Option, #[default(None)] - pub iframely_url: Option, - #[default(None)] pub additional_slurs: Option, #[default(20)] pub actor_name_max_length: usize, diff --git a/crates/websocket/src/lib.rs b/crates/websocket/src/lib.rs index b866a2a21..e01514030 100644 --- a/crates/websocket/src/lib.rs +++ b/crates/websocket/src/lib.rs @@ -125,6 +125,7 @@ pub enum UserOperation { CommunityJoin, ModJoin, ChangePassword, + GetSiteMetadata, } #[derive(EnumString, ToString, Debug, Clone)] diff --git a/docker/dev/docker-compose.yml b/docker/dev/docker-compose.yml index a9e580a4b..bc42d4562 100644 --- a/docker/dev/docker-compose.yml +++ b/docker/dev/docker-compose.yml @@ -14,7 +14,6 @@ services: depends_on: - pictrs - postgres - - iframely lemmy-ui: image: dessalines/lemmy-ui:dev @@ -49,12 +48,3 @@ services: volumes: - ./volumes/pictrs:/mnt restart: always - - iframely: - image: dogbin/iframely:latest - ports: - - "8061:80" - volumes: - - ../iframely.config.local.js:/iframely/config.local.js:ro - restart: always - mem_limit: 200m diff --git a/docker/dev/volume_mount.dockerfile b/docker/dev/volume_mount.dockerfile index ae902e938..0af2a37f6 100644 --- a/docker/dev/volume_mount.dockerfile +++ b/docker/dev/volume_mount.dockerfile @@ -22,7 +22,7 @@ FROM ubuntu:20.10 # Install libpq for postgres RUN apt-get update -y -RUN apt-get install -y libpq-dev +RUN apt-get install -y libpq-dev ca-certificates # Copy resources COPY --from=rust /app/lemmy_server /app/lemmy diff --git a/docker/federation/docker-compose.yml b/docker/federation/docker-compose.yml index a9d8863d3..c2f05c175 100644 --- a/docker/federation/docker-compose.yml +++ b/docker/federation/docker-compose.yml @@ -14,7 +14,6 @@ services: restart: on-failure depends_on: - pictrs - - iframely - lemmy-alpha-ui - lemmy-beta-ui - lemmy-gamma-ui @@ -174,9 +173,3 @@ services: - POSTGRES_DB=lemmy volumes: - ./volumes/postgres_epsilon:/var/lib/postgresql/data - - iframely: - image: dogbin/iframely:latest - volumes: - - ../iframely.config.local.js:/iframely/config.local.js:ro - restart: always diff --git a/docker/federation/nginx.conf b/docker/federation/nginx.conf index 8bf2ed7f2..425371bee 100644 --- a/docker/federation/nginx.conf +++ b/docker/federation/nginx.conf @@ -40,12 +40,6 @@ http { # Cuts off the trailing slash on URLs to make them valid rewrite ^(.+)/+$ $1 permanent; } - location /iframely/ { - proxy_pass http://iframely:80/; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } } upstream lemmy-beta { @@ -85,12 +79,6 @@ http { # Cuts off the trailing slash on URLs to make them valid rewrite ^(.+)/+$ $1 permanent; } - location /iframely/ { - proxy_pass http://iframely:80/; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } } upstream lemmy-gamma { @@ -130,12 +118,6 @@ http { # Cuts off the trailing slash on URLs to make them valid rewrite ^(.+)/+$ $1 permanent; } - location /iframely/ { - proxy_pass http://iframely:80/; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } } upstream lemmy-delta { @@ -175,12 +157,6 @@ http { # Cuts off the trailing slash on URLs to make them valid rewrite ^(.+)/+$ $1 permanent; } - location /iframely/ { - proxy_pass http://iframely:80/; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } } upstream lemmy-epsilon { @@ -220,11 +196,5 @@ http { # Cuts off the trailing slash on URLs to make them valid rewrite ^(.+)/+$ $1 permanent; } - location /iframely/ { - proxy_pass http://iframely:80/; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } } } diff --git a/docker/iframely.config.local.js b/docker/iframely.config.local.js deleted file mode 100644 index 8e8bc21fb..000000000 --- a/docker/iframely.config.local.js +++ /dev/null @@ -1,283 +0,0 @@ -(function() { - var config = { - - // Specify a path for custom plugins. Custom plugins will override core plugins. - // CUSTOM_PLUGINS_PATH: __dirname + '/yourcustom-plugin-folder', - - DEBUG: false, - RICH_LOG_ENABLED: false, - - // For embeds that require render, baseAppUrl will be used as the host. - baseAppUrl: "http://yourdomain.com", - relativeStaticUrl: "/r", - - // Or just skip built-in renders altogether - SKIP_IFRAMELY_RENDERS: true, - - // For legacy reasons the response format of Iframely open-source is - // different by default as it does not group the links array by rel. - // In order to get the same grouped response as in Cloud API, - // add `&group=true` to your request to change response per request - // or set `GROUP_LINKS` in your config to `true` for a global change. - GROUP_LINKS: true, - - // Number of maximum redirects to follow before aborting the page - // request with `redirect loop` error. - MAX_REDIRECTS: 4, - - SKIP_OEMBED_RE_LIST: [ - // /^https?:\/\/yourdomain\.com\//, - ], - - /* - // Used to pass parameters to the generate functions when creating HTML elements - // disableSizeWrapper: Don't wrap element (iframe, video, etc) in a positioned div - GENERATE_LINK_PARAMS: { - disableSizeWrapper: true - }, - */ - - port: 80, //can be overridden by PORT env var - host: '0.0.0.0', // Dockers beware. See https://github.com/itteco/iframely/issues/132#issuecomment-242991246 - //can be overridden by HOST env var - - // Optional SSL cert, if you serve under HTTPS. - /* - ssl: { - key: require('fs').readFileSync(__dirname + '/key.pem'), - cert: require('fs').readFileSync(__dirname + '/cert.pem'), - port: 443 - }, - */ - - /* - Supported cache engines: - - no-cache - no caching will be used. - - node-cache - good for debug, node memory will be used (https://github.com/tcs-de/nodecache). - - redis - https://github.com/mranney/node_redis. - - memcached - https://github.com/3rd-Eden/node-memcached - */ - CACHE_ENGINE: 'node-cache', - CACHE_TTL: 0, // In seconds. - // 0 = 'never expire' for memcached & node-cache to let cache engine decide itself when to evict the record - // 0 = 'no cache' for redis. Use high enough (e.g. 365*24*60*60*1000) ttl for similar 'never expire' approach instead - - /* - // Redis cache options. - REDIS_OPTIONS: { - host: '127.0.0.1', - port: 6379 - }, - */ - - /* - // Memcached options. See https://github.com/3rd-Eden/node-memcached#server-locations - MEMCACHED_OPTIONS: { - locations: "127.0.0.1:11211" - } - */ - - /* - // Access-Control-Allow-Origin list. - allowedOrigins: [ - "*", - "http://another_domain.com" - ], - */ - - /* - // Uncomment to enable plugin testing framework. - tests: { - mongodb: 'mongodb://localhost:27017/iframely-tests', - single_test_timeout: 10 * 1000, - plugin_test_period: 2 * 60 * 60 * 1000, - relaunch_script_period: 5 * 60 * 1000 - }, - */ - - // If there's no response from remote server, the timeout will occur after - RESPONSE_TIMEOUT: 5 * 1000, //ms - - /* From v1.4.0, Iframely supports HTTP/2 by default. Disable it, if you'd rather not. - Alternatively, you can also disable per origin. See `proxy` option below. - */ - // DISABLE_HTTP2: true, - - // Customize API calls to oembed endpoints. - ADD_OEMBED_PARAMS: [{ - // Endpoint url regexp array. - re: [/^http:\/\/api\.instagram\.com\/oembed/], - // Custom get params object. - params: { - hidecaption: true - } - }, { - re: [/^https:\/\/www\.facebook\.com\/plugins\/page\/oembed\.json/i], - params: { - show_posts: 0, - show_facepile: 0, - maxwidth: 600 - } - }, { - // match i=user or i=moment or i=timeline to configure these types invidually - // see params spec at https://dev.twitter.com/web/embedded-timelines/oembed - re: [/^https?:\/\/publish\.twitter\.com\/oembed\?i=user/i], - params: { - limit: 1, - maxwidth: 600 - } - /* - }, { - // Facebook https://developers.facebook.com/docs/plugins/oembed-endpoints - re: [/^https:\/\/www\.facebook\.com\/plugins\/\w+\/oembed\.json/i], - params: { - // Skip script tag and fb-root div. - omitscript: true - } - */ - }], - - /* - // Configure use of HTTP proxies as needed. - // You don't have to specify all options per regex - just what you need to override - PROXY: [{ - re: [/^https?:\/\/www\.domain\.com/], - proxy_server: 'http://1.2.3.4:8080', - user_agent: 'CHANGE YOUR AGENT', - headers: { - // HTTP headers - // Overrides previous params if overlapped. - }, - request_options: { - // Refer to: https://github.com/request/request - // Overrides previous params if overlapped. - }, - disable_http2: true - }], - */ - - // Customize API calls to 3rd parties. At the very least - configure required keys. - providerOptions: { - locale: "en_US", // ISO 639-1 two-letter language code, e.g. en_CA or fr_CH. - // Will be added as highest priotity in accept-language header with each request. - // Plus is used in FB, YouTube and perhaps other plugins - "twitter": { - "max-width": 550, - "min-width": 250, - hide_media: false, - hide_thread: false, - omit_script: false, - center: false, - // dnt: true, - cache_ttl: 100 * 365 * 24 * 3600 // 100 Years. - }, - readability: { - enabled: false - // allowPTagDescription: true // to enable description fallback to first paragraph - }, - images: { - loadSize: false, // if true, will try an load first bytes of all images to get/confirm the sizes - checkFavicon: false // if true, will verify all favicons - }, - tumblr: { - consumer_key: "INSERT YOUR VALUE" - // media_only: true // disables status embeds for images and videos - will return plain media - }, - google: { - // https://developers.google.com/maps/documentation/embed/guide#api_key - maps_key: "INSERT YOUR VALUE" - }, - - /* - // Optional Camo Proxy to wrap all images: https://github.com/atmos/camo - camoProxy: { - camo_proxy_key: "INSERT YOUR VALUE", - camo_proxy_host: "INSERT YOUR VALUE" - // ssl_only: true // will only proxy non-ssl images - }, - */ - - // List of query parameters to add to YouTube and Vimeo frames - // Start it with leading "?". Or omit alltogether for default values - // API key is optional, youtube will work without it too. - // It is probably the same API key you use for Google Maps. - youtube: { - // api_key: "INSERT YOUR VALUE", - get_params: "?rel=0&showinfo=1" // https://developers.google.com/youtube/player_parameters - }, - vimeo: { - get_params: "?byline=0&badge=0" // https://developer.vimeo.com/player/embedding - }, - - /* - soundcloud: { - old_player: true // enables classic player - }, - giphy: { - media_only: true // disables branded player for gifs and returns just the image - } - */ - /* - bandcamp: { - get_params: '/size=large/bgcol=333333/linkcol=ffffff/artwork=small/transparent=true/', - media: { - album: { - height: 472, - 'max-width': 700 - }, - track: { - height: 120, - 'max-width': 700 - } - } - } - */ - }, - - // WHITELIST_WILDCARD, if present, will be added to whitelist as record for top level domain: "*" - // with it, you can define what parsers do when they run accross unknown publisher. - // If absent or empty, all generic media parsers will be disabled except for known domains - // More about format: https://iframely.com/docs/qa-format - - /* - WHITELIST_WILDCARD: { - "twitter": { - "player": "allow", - "photo": "deny" - }, - "oembed": { - "video": "allow", - "photo": "allow", - "rich": "deny", - "link": "deny" - }, - "og": { - "video": ["allow", "ssl", "responsive"] - }, - "iframely": { - "survey": "allow", - "reader": "allow", - "player": "allow", - "image": "allow" - }, - "html-meta": { - "video": ["allow", "responsive"], - "promo": "allow" - } - } - */ - - // Black-list any of the inappropriate domains. Iframely will return 417 - // At minimum, keep your localhosts blacklisted to avoid SSRF - BLACKLIST_DOMAINS_RE: [ - /^https?:\/\/127\.0\.0\.1/i, - /^https?:\/\/localhost/i, - - // And this is AWS metadata service - // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html - /^https?:\/\/169\.254\.169\.254/ - ] - }; - - module.exports = config; -})(); diff --git a/docker/lemmy.hjson b/docker/lemmy.hjson index 8f117e30e..53f0ff170 100644 --- a/docker/lemmy.hjson +++ b/docker/lemmy.hjson @@ -20,6 +20,8 @@ # json web token for authorization between server and client jwt_secret: "changeme" # settings related to the postgresql database + # address where pictrs is available + pictrs_url: "http://pictrs:8080" database: { # name of the postgres database for lemmy database: "lemmy" diff --git a/docker/prod/docker-compose.yml b/docker/prod/docker-compose.yml index 807faa115..a68c4987b 100644 --- a/docker/prod/docker-compose.yml +++ b/docker/prod/docker-compose.yml @@ -23,7 +23,6 @@ services: depends_on: - postgres - pictrs - - iframely lemmy-ui: image: dessalines/lemmy-ui:0.11.3 @@ -46,11 +45,3 @@ services: - ./volumes/pictrs:/mnt restart: always - iframely: - image: dogbin/iframely:latest - ports: - - "127.0.0.1:8061:80" - volumes: - - ./iframely.config.local.js:/iframely/config.local.js:ro - restart: always - mem_limit: 200m diff --git a/src/api_routes.rs b/src/api_routes.rs index f8e8f7e18..a3bf39fe1 100644 --- a/src/api_routes.rs +++ b/src/api_routes.rs @@ -88,7 +88,11 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) { "/report/resolve", web::put().to(route_post::), ) - .route("/report/list", web::get().to(route_get::)), + .route("/report/list", web::get().to(route_get::)) + .route( + "/site_metadata", + web::get().to(route_get::), + ), ) // Comment .service( diff --git a/src/main.rs b/src/main.rs index 6b4ac3697..504ccc80e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -66,6 +66,7 @@ async fn main() -> Result<(), LemmyError> { ); let activity_queue = create_activity_queue(); + let chat_server = ChatServer::startup( pool.clone(), rate_limiter.clone(),