From 14f2d190e5060d4af4bc964a4ce75970add215e1 Mon Sep 17 00:00:00 2001 From: nutomic Date: Tue, 18 Aug 2020 13:43:50 +0000 Subject: [PATCH] Implement context (#86) Implement context Co-authored-by: Felix Ableitner Reviewed-on: https://yerbamate.dev/LemmyNet/lemmy/pulls/86 --- server/src/api/comment.rs | 241 +++++++++------- server/src/api/community.rs | 219 ++++++++------- server/src/api/mod.rs | 14 +- server/src/api/post.rs | 213 +++++++------- server/src/api/site.rs | 141 +++++----- server/src/api/user.rs | 277 ++++++++++--------- server/src/apub/activities.rs | 11 +- server/src/apub/comment.rs | 224 +++++++-------- server/src/apub/community.rs | 132 ++++----- server/src/apub/fetcher.rs | 175 ++++++------ server/src/apub/inbox/activities/announce.rs | 23 +- server/src/apub/inbox/activities/create.rs | 61 ++-- server/src/apub/inbox/activities/delete.rs | 79 +++--- server/src/apub/inbox/activities/dislike.rs | 56 ++-- server/src/apub/inbox/activities/like.rs | 59 ++-- server/src/apub/inbox/activities/remove.rs | 81 +++--- server/src/apub/inbox/activities/undo.rs | 276 +++++++++--------- server/src/apub/inbox/activities/update.rs | 64 ++--- server/src/apub/inbox/community_inbox.rs | 32 +-- server/src/apub/inbox/shared_inbox.rs | 42 ++- server/src/apub/inbox/user_inbox.rs | 97 +++---- server/src/apub/mod.rs | 100 ++----- server/src/apub/post.rs | 189 ++++++------- server/src/apub/private_message.rs | 106 ++++--- server/src/apub/user.rs | 63 ++--- server/src/lib.rs | 41 ++- server/src/main.rs | 11 +- server/src/routes/api.rs | 24 +- server/src/routes/feeds.rs | 24 +- server/src/routes/mod.rs | 11 - server/src/routes/nodeinfo.rs | 6 +- server/src/routes/webfinger.rs | 16 +- server/src/routes/websocket.rs | 5 +- server/src/websocket/server.rs | 29 +- 34 files changed, 1535 insertions(+), 1607 deletions(-) diff --git a/server/src/api/comment.rs b/server/src/api/comment.rs index dc76b6b5a..63f53a4d7 100644 --- a/server/src/api/comment.rs +++ b/server/src/api/comment.rs @@ -15,9 +15,10 @@ use crate::{ WebsocketInfo, }, DbPool, + LemmyContext, LemmyError, }; -use actix_web::client::Client; +use actix_web::web::Data; use lemmy_db::{ comment::*, comment_view::*, @@ -126,12 +127,11 @@ impl Perform for CreateComment { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &CreateComment = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let content_slurs_removed = remove_slurs(&data.content.to_owned()); @@ -151,9 +151,9 @@ impl Perform for CreateComment { // Check for a community ban let post_id = data.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; - check_community_ban(user.id, post.community_id, pool).await?; + check_community_ban(user.id, post.community_id, context.pool()).await?; // Check if post is locked, no new comments if post.locked { @@ -162,15 +162,18 @@ impl Perform for CreateComment { // Create the comment let comment_form2 = comment_form.clone(); - let inserted_comment = - match blocking(pool, move |conn| Comment::create(&conn, &comment_form2)).await? { - Ok(comment) => comment, - Err(_e) => return Err(APIError::err("couldnt_create_comment").into()), - }; + let inserted_comment = match blocking(context.pool(), move |conn| { + Comment::create(&conn, &comment_form2) + }) + .await? + { + Ok(comment) => comment, + Err(_e) => return Err(APIError::err("couldnt_create_comment").into()), + }; // Necessary to update the ap_id let inserted_comment_id = inserted_comment.id; - let updated_comment: Comment = match blocking(pool, move |conn| { + let updated_comment: Comment = match blocking(context.pool(), move |conn| { let apub_id = make_apub_endpoint(EndpointType::Comment, &inserted_comment_id.to_string()).to_string(); Comment::update_ap_id(&conn, inserted_comment_id, apub_id) @@ -181,12 +184,19 @@ impl Perform for CreateComment { Err(_e) => return Err(APIError::err("couldnt_create_comment").into()), }; - updated_comment.send_create(&user, &client, pool).await?; + updated_comment.send_create(&user, context).await?; // Scan the comment for user mentions, add those rows let mentions = scrape_text_for_mentions(&comment_form.content); - let recipient_ids = - send_local_notifs(mentions, updated_comment.clone(), &user, post, pool, true).await?; + let recipient_ids = send_local_notifs( + mentions, + updated_comment.clone(), + &user, + post, + context.pool(), + true, + ) + .await?; // You like your own comment by default let like_form = CommentLikeForm { @@ -197,14 +207,14 @@ impl Perform for CreateComment { }; let like = move |conn: &'_ _| CommentLike::like(&conn, &like_form); - if blocking(pool, like).await?.is_err() { + if blocking(context.pool(), like).await?.is_err() { return Err(APIError::err("couldnt_like_comment").into()); } - updated_comment.send_like(&user, &client, pool).await?; + updated_comment.send_like(&user, context).await?; let user_id = user.id; - let comment_view = blocking(pool, move |conn| { + let comment_view = blocking(context.pool(), move |conn| { CommentView::read(&conn, inserted_comment.id, Some(user_id)) }) .await??; @@ -237,18 +247,19 @@ impl Perform for EditComment { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &EditComment = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let edit_id = data.edit_id; - let orig_comment = - blocking(pool, move |conn| CommentView::read(&conn, edit_id, None)).await??; + let orig_comment = blocking(context.pool(), move |conn| { + CommentView::read(&conn, edit_id, None) + }) + .await??; - check_community_ban(user.id, orig_comment.community_id, pool).await?; + check_community_ban(user.id, orig_comment.community_id, context.pool()).await?; // Verify that only the creator can edit if user.id != orig_comment.creator_id { @@ -258,7 +269,7 @@ impl Perform for EditComment { // Do the update let content_slurs_removed = remove_slurs(&data.content.to_owned()); let edit_id = data.edit_id; - let updated_comment = match blocking(pool, move |conn| { + let updated_comment = match blocking(context.pool(), move |conn| { Comment::update_content(conn, edit_id, &content_slurs_removed) }) .await? @@ -268,20 +279,27 @@ impl Perform for EditComment { }; // Send the apub update - updated_comment.send_update(&user, &client, pool).await?; + updated_comment.send_update(&user, context).await?; // Do the mentions / recipients let post_id = orig_comment.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let updated_comment_content = updated_comment.content.to_owned(); let mentions = scrape_text_for_mentions(&updated_comment_content); - let recipient_ids = - send_local_notifs(mentions, updated_comment, &user, post, pool, false).await?; + let recipient_ids = send_local_notifs( + mentions, + updated_comment, + &user, + post, + context.pool(), + false, + ) + .await?; let edit_id = data.edit_id; let user_id = user.id; - let comment_view = blocking(pool, move |conn| { + let comment_view = blocking(context.pool(), move |conn| { CommentView::read(conn, edit_id, Some(user_id)) }) .await??; @@ -314,18 +332,19 @@ impl Perform for DeleteComment { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &DeleteComment = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let edit_id = data.edit_id; - let orig_comment = - blocking(pool, move |conn| CommentView::read(&conn, edit_id, None)).await??; + let orig_comment = blocking(context.pool(), move |conn| { + CommentView::read(&conn, edit_id, None) + }) + .await??; - check_community_ban(user.id, orig_comment.community_id, pool).await?; + check_community_ban(user.id, orig_comment.community_id, context.pool()).await?; // Verify that only the creator can delete if user.id != orig_comment.creator_id { @@ -334,7 +353,7 @@ impl Perform for DeleteComment { // Do the delete let deleted = data.deleted; - let updated_comment = match blocking(pool, move |conn| { + let updated_comment = match blocking(context.pool(), move |conn| { Comment::update_deleted(conn, edit_id, deleted) }) .await? @@ -345,27 +364,32 @@ impl Perform for DeleteComment { // Send the apub message if deleted { - updated_comment.send_delete(&user, &client, pool).await?; + updated_comment.send_delete(&user, context).await?; } else { - updated_comment - .send_undo_delete(&user, &client, pool) - .await?; + updated_comment.send_undo_delete(&user, context).await?; } // Refetch it let edit_id = data.edit_id; let user_id = user.id; - let comment_view = blocking(pool, move |conn| { + let comment_view = blocking(context.pool(), move |conn| { CommentView::read(conn, edit_id, Some(user_id)) }) .await??; // Build the recipients let post_id = comment_view.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let mentions = vec![]; - let recipient_ids = - send_local_notifs(mentions, updated_comment, &user, post, pool, false).await?; + let recipient_ids = send_local_notifs( + mentions, + updated_comment, + &user, + post, + context.pool(), + false, + ) + .await?; let mut res = CommentResponse { comment: comment_view, @@ -395,25 +419,26 @@ impl Perform for RemoveComment { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &RemoveComment = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let edit_id = data.edit_id; - let orig_comment = - blocking(pool, move |conn| CommentView::read(&conn, edit_id, None)).await??; + let orig_comment = blocking(context.pool(), move |conn| { + CommentView::read(&conn, edit_id, None) + }) + .await??; - check_community_ban(user.id, orig_comment.community_id, pool).await?; + check_community_ban(user.id, orig_comment.community_id, context.pool()).await?; // Verify that only a mod or admin can remove - is_mod_or_admin(pool, user.id, orig_comment.community_id).await?; + is_mod_or_admin(context.pool(), user.id, orig_comment.community_id).await?; // Do the remove let removed = data.removed; - let updated_comment = match blocking(pool, move |conn| { + let updated_comment = match blocking(context.pool(), move |conn| { Comment::update_removed(conn, edit_id, removed) }) .await? @@ -429,31 +454,39 @@ impl Perform for RemoveComment { removed: Some(removed), reason: data.reason.to_owned(), }; - blocking(pool, move |conn| ModRemoveComment::create(conn, &form)).await??; + blocking(context.pool(), move |conn| { + ModRemoveComment::create(conn, &form) + }) + .await??; // Send the apub message if removed { - updated_comment.send_remove(&user, &client, pool).await?; + updated_comment.send_remove(&user, context).await?; } else { - updated_comment - .send_undo_remove(&user, &client, pool) - .await?; + updated_comment.send_undo_remove(&user, context).await?; } // Refetch it let edit_id = data.edit_id; let user_id = user.id; - let comment_view = blocking(pool, move |conn| { + let comment_view = blocking(context.pool(), move |conn| { CommentView::read(conn, edit_id, Some(user_id)) }) .await??; // Build the recipients let post_id = comment_view.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let mentions = vec![]; - let recipient_ids = - send_local_notifs(mentions, updated_comment, &user, post, pool, false).await?; + let recipient_ids = send_local_notifs( + mentions, + updated_comment, + &user, + post, + context.pool(), + false, + ) + .await?; let mut res = CommentResponse { comment: comment_view, @@ -483,33 +516,37 @@ impl Perform for MarkCommentAsRead { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &MarkCommentAsRead = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let edit_id = data.edit_id; - let orig_comment = - blocking(pool, move |conn| CommentView::read(&conn, edit_id, None)).await??; + let orig_comment = blocking(context.pool(), move |conn| { + CommentView::read(&conn, edit_id, None) + }) + .await??; - check_community_ban(user.id, orig_comment.community_id, pool).await?; + check_community_ban(user.id, orig_comment.community_id, context.pool()).await?; // Verify that only the recipient can mark as read // Needs to fetch the parent comment / post to get the recipient let parent_id = orig_comment.parent_id; match parent_id { Some(pid) => { - let parent_comment = - blocking(pool, move |conn| CommentView::read(&conn, pid, None)).await??; + let parent_comment = blocking(context.pool(), move |conn| { + CommentView::read(&conn, pid, None) + }) + .await??; if user.id != parent_comment.creator_id { return Err(APIError::err("no_comment_edit_allowed").into()); } } None => { let parent_post_id = orig_comment.post_id; - let parent_post = blocking(pool, move |conn| Post::read(conn, parent_post_id)).await??; + let parent_post = + blocking(context.pool(), move |conn| Post::read(conn, parent_post_id)).await??; if user.id != parent_post.creator_id { return Err(APIError::err("no_comment_edit_allowed").into()); } @@ -518,7 +555,11 @@ impl Perform for MarkCommentAsRead { // Do the mark as read let read = data.read; - match blocking(pool, move |conn| Comment::update_read(conn, edit_id, read)).await? { + match blocking(context.pool(), move |conn| { + Comment::update_read(conn, edit_id, read) + }) + .await? + { Ok(comment) => comment, Err(_e) => return Err(APIError::err("couldnt_update_comment").into()), }; @@ -526,7 +567,7 @@ impl Perform for MarkCommentAsRead { // Refetch it let edit_id = data.edit_id; let user_id = user.id; - let comment_view = blocking(pool, move |conn| { + let comment_view = blocking(context.pool(), move |conn| { CommentView::read(conn, edit_id, Some(user_id)) }) .await??; @@ -547,12 +588,11 @@ impl Perform for SaveComment { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &SaveComment = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let comment_saved_form = CommentSavedForm { comment_id: data.comment_id, @@ -561,19 +601,19 @@ impl Perform for SaveComment { if data.save { let save_comment = move |conn: &'_ _| CommentSaved::save(conn, &comment_saved_form); - if blocking(pool, save_comment).await?.is_err() { + if blocking(context.pool(), save_comment).await?.is_err() { return Err(APIError::err("couldnt_save_comment").into()); } } else { let unsave_comment = move |conn: &'_ _| CommentSaved::unsave(conn, &comment_saved_form); - if blocking(pool, unsave_comment).await?.is_err() { + if blocking(context.pool(), unsave_comment).await?.is_err() { return Err(APIError::err("couldnt_save_comment").into()); } } let comment_id = data.comment_id; let user_id = user.id; - let comment_view = blocking(pool, move |conn| { + let comment_view = blocking(context.pool(), move |conn| { CommentView::read(conn, comment_id, Some(user_id)) }) .await??; @@ -592,40 +632,42 @@ impl Perform for CreateCommentLike { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &CreateCommentLike = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let mut recipient_ids = Vec::new(); // Don't do a downvote if site has downvotes disabled if data.score == -1 { - let site = blocking(pool, move |conn| SiteView::read(conn)).await??; + let site = blocking(context.pool(), move |conn| SiteView::read(conn)).await??; if !site.enable_downvotes { return Err(APIError::err("downvotes_disabled").into()); } } let comment_id = data.comment_id; - let orig_comment = - blocking(pool, move |conn| CommentView::read(&conn, comment_id, None)).await??; + let orig_comment = blocking(context.pool(), move |conn| { + CommentView::read(&conn, comment_id, None) + }) + .await??; let post_id = orig_comment.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; - check_community_ban(user.id, post.community_id, pool).await?; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; + check_community_ban(user.id, post.community_id, context.pool()).await?; let comment_id = data.comment_id; - let comment = blocking(pool, move |conn| Comment::read(conn, comment_id)).await??; + let comment = blocking(context.pool(), move |conn| Comment::read(conn, comment_id)).await??; // Add to recipient ids match comment.parent_id { Some(parent_id) => { - let parent_comment = blocking(pool, move |conn| Comment::read(conn, parent_id)).await??; + let parent_comment = + blocking(context.pool(), move |conn| Comment::read(conn, parent_id)).await??; if parent_comment.creator_id != user.id { - let parent_user = blocking(pool, move |conn| { + let parent_user = blocking(context.pool(), move |conn| { User_::read(conn, parent_comment.creator_id) }) .await??; @@ -646,7 +688,7 @@ impl Perform for CreateCommentLike { // Remove any likes first let user_id = user.id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { CommentLike::remove(conn, user_id, comment_id) }) .await??; @@ -656,23 +698,23 @@ impl Perform for CreateCommentLike { if do_add { let like_form2 = like_form.clone(); let like = move |conn: &'_ _| CommentLike::like(conn, &like_form2); - if blocking(pool, like).await?.is_err() { + if blocking(context.pool(), like).await?.is_err() { return Err(APIError::err("couldnt_like_comment").into()); } if like_form.score == 1 { - comment.send_like(&user, &client, pool).await?; + comment.send_like(&user, context).await?; } else if like_form.score == -1 { - comment.send_dislike(&user, &client, pool).await?; + comment.send_dislike(&user, context).await?; } } else { - comment.send_undo_like(&user, &client, pool).await?; + comment.send_undo_like(&user, context).await?; } // Have to refetch the comment to get the current state let comment_id = data.comment_id; let user_id = user.id; - let liked_comment = blocking(pool, move |conn| { + let liked_comment = blocking(context.pool(), move |conn| { CommentView::read(conn, comment_id, Some(user_id)) }) .await??; @@ -705,12 +747,11 @@ impl Perform for GetComments { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - _client: Client, ) -> Result { let data: &GetComments = &self; - let user = get_user_from_jwt_opt(&data.auth, pool).await?; + let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?; let user_id = user.map(|u| u.id); let type_ = ListingType::from_str(&data.type_)?; @@ -719,7 +760,7 @@ impl Perform for GetComments { let community_id = data.community_id; let page = data.page; let limit = data.limit; - let comments = blocking(pool, move |conn| { + let comments = blocking(context.pool(), move |conn| { CommentQueryBuilder::create(conn) .listing_type(type_) .sort(&sort) diff --git a/server/src/api/community.rs b/server/src/api/community.rs index bd6714563..f5fffb7c2 100644 --- a/server/src/api/community.rs +++ b/server/src/api/community.rs @@ -8,9 +8,7 @@ use crate::{ UserOperation, WebsocketInfo, }, - DbPool, }; -use actix_web::client::Client; use anyhow::Context; use lemmy_db::{ comment::Comment, @@ -167,25 +165,28 @@ impl Perform for GetCommunity { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - _client: Client, ) -> Result { let data: &GetCommunity = &self; - let user = get_user_from_jwt_opt(&data.auth, pool).await?; + let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?; let user_id = user.map(|u| u.id); let name = data.name.to_owned().unwrap_or_else(|| "main".to_string()); let community = match data.id { - Some(id) => blocking(pool, move |conn| Community::read(conn, id)).await??, - None => match blocking(pool, move |conn| Community::read_from_name(conn, &name)).await? { + Some(id) => blocking(context.pool(), move |conn| Community::read(conn, id)).await??, + None => match blocking(context.pool(), move |conn| { + Community::read_from_name(conn, &name) + }) + .await? + { Ok(community) => community, Err(_e) => return Err(APIError::err("couldnt_find_community").into()), }, }; let community_id = community.id; - let community_view = match blocking(pool, move |conn| { + let community_view = match blocking(context.pool(), move |conn| { CommunityView::read(conn, community_id, user_id) }) .await? @@ -195,7 +196,7 @@ impl Perform for GetCommunity { }; let community_id = community.id; - let moderators: Vec = match blocking(pool, move |conn| { + let moderators: Vec = match blocking(context.pool(), move |conn| { CommunityModeratorView::for_community(conn, community_id) }) .await? @@ -236,12 +237,11 @@ impl Perform for CreateCommunity { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &CreateCommunity = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; check_slurs(&data.name)?; check_slurs(&data.title)?; @@ -254,7 +254,7 @@ impl Perform for CreateCommunity { // Double check for duplicate community actor_ids let actor_id = make_apub_endpoint(EndpointType::Community, &data.name).to_string(); let actor_id_cloned = actor_id.to_owned(); - let community_dupe = blocking(pool, move |conn| { + let community_dupe = blocking(context.pool(), move |conn| { Community::read_from_actor_id(conn, &actor_id_cloned) }) .await?; @@ -285,11 +285,14 @@ impl Perform for CreateCommunity { published: None, }; - let inserted_community = - match blocking(pool, move |conn| Community::create(conn, &community_form)).await? { - Ok(community) => community, - Err(_e) => return Err(APIError::err("community_already_exists").into()), - }; + let inserted_community = match blocking(context.pool(), move |conn| { + Community::create(conn, &community_form) + }) + .await? + { + Ok(community) => community, + Err(_e) => return Err(APIError::err("community_already_exists").into()), + }; let community_moderator_form = CommunityModeratorForm { community_id: inserted_community.id, @@ -297,7 +300,7 @@ impl Perform for CreateCommunity { }; let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form); - if blocking(pool, join).await?.is_err() { + if blocking(context.pool(), join).await?.is_err() { return Err(APIError::err("community_moderator_already_exists").into()); } @@ -307,12 +310,12 @@ impl Perform for CreateCommunity { }; let follow = move |conn: &'_ _| CommunityFollower::follow(conn, &community_follower_form); - if blocking(pool, follow).await?.is_err() { + if blocking(context.pool(), follow).await?.is_err() { return Err(APIError::err("community_follower_already_exists").into()); } let user_id = user.id; - let community_view = blocking(pool, move |conn| { + let community_view = blocking(context.pool(), move |conn| { CommunityView::read(conn, inserted_community.id, Some(user_id)) }) .await??; @@ -329,19 +332,18 @@ impl Perform for EditCommunity { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - _client: Client, ) -> Result { let data: &EditCommunity = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; check_slurs(&data.title)?; check_slurs_opt(&data.description)?; // Verify its a mod (only mods can edit it) let edit_id = data.edit_id; - let mods: Vec = blocking(pool, move |conn| { + let mods: Vec = blocking(context.pool(), move |conn| { CommunityModeratorView::for_community(conn, edit_id) .map(|v| v.into_iter().map(|m| m.user_id).collect()) }) @@ -351,7 +353,8 @@ impl Perform for EditCommunity { } let edit_id = data.edit_id; - let read_community = blocking(pool, move |conn| Community::read(conn, edit_id)).await??; + let read_community = + blocking(context.pool(), move |conn| Community::read(conn, edit_id)).await??; let icon = diesel_option_overwrite(&data.icon); let banner = diesel_option_overwrite(&data.banner); @@ -377,7 +380,7 @@ impl Perform for EditCommunity { }; let edit_id = data.edit_id; - match blocking(pool, move |conn| { + match blocking(context.pool(), move |conn| { Community::update(conn, edit_id, &community_form) }) .await? @@ -391,7 +394,7 @@ impl Perform for EditCommunity { let edit_id = data.edit_id; let user_id = user.id; - let community_view = blocking(pool, move |conn| { + let community_view = blocking(context.pool(), move |conn| { CommunityView::read(conn, edit_id, Some(user_id)) }) .await??; @@ -412,16 +415,16 @@ impl Perform for DeleteCommunity { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &DeleteCommunity = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; // Verify its the creator (only a creator can delete the community) let edit_id = data.edit_id; - let read_community = blocking(pool, move |conn| Community::read(conn, edit_id)).await??; + let read_community = + blocking(context.pool(), move |conn| Community::read(conn, edit_id)).await??; if read_community.creator_id != user.id { return Err(APIError::err("no_community_edit_allowed").into()); } @@ -429,7 +432,7 @@ impl Perform for DeleteCommunity { // Do the delete let edit_id = data.edit_id; let deleted = data.deleted; - let updated_community = match blocking(pool, move |conn| { + let updated_community = match blocking(context.pool(), move |conn| { Community::update_deleted(conn, edit_id, deleted) }) .await? @@ -440,16 +443,14 @@ impl Perform for DeleteCommunity { // Send apub messages if deleted { - updated_community.send_delete(&user, &client, pool).await?; + updated_community.send_delete(&user, context).await?; } else { - updated_community - .send_undo_delete(&user, &client, pool) - .await?; + updated_community.send_undo_delete(&user, context).await?; } let edit_id = data.edit_id; let user_id = user.id; - let community_view = blocking(pool, move |conn| { + let community_view = blocking(context.pool(), move |conn| { CommunityView::read(conn, edit_id, Some(user_id)) }) .await??; @@ -470,20 +471,19 @@ impl Perform for RemoveCommunity { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &RemoveCommunity = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; // Verify its an admin (only an admin can remove a community) - is_admin(pool, user.id).await?; + is_admin(context.pool(), user.id).await?; // Do the remove let edit_id = data.edit_id; let removed = data.removed; - let updated_community = match blocking(pool, move |conn| { + let updated_community = match blocking(context.pool(), move |conn| { Community::update_removed(conn, edit_id, removed) }) .await? @@ -504,20 +504,21 @@ impl Perform for RemoveCommunity { reason: data.reason.to_owned(), expires, }; - blocking(pool, move |conn| ModRemoveCommunity::create(conn, &form)).await??; + blocking(context.pool(), move |conn| { + ModRemoveCommunity::create(conn, &form) + }) + .await??; // Apub messages if removed { - updated_community.send_remove(&user, &client, pool).await?; + updated_community.send_remove(&user, context).await?; } else { - updated_community - .send_undo_remove(&user, &client, pool) - .await?; + updated_community.send_undo_remove(&user, context).await?; } let edit_id = data.edit_id; let user_id = user.id; - let community_view = blocking(pool, move |conn| { + let community_view = blocking(context.pool(), move |conn| { CommunityView::read(conn, edit_id, Some(user_id)) }) .await??; @@ -538,12 +539,11 @@ impl Perform for ListCommunities { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &ListCommunities = &self; - let user = get_user_from_jwt_opt(&data.auth, pool).await?; + let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?; let user_id = match &user { Some(user) => Some(user.id), @@ -559,7 +559,7 @@ impl Perform for ListCommunities { let page = data.page; let limit = data.limit; - let communities = blocking(pool, move |conn| { + let communities = blocking(context.pool(), move |conn| { CommunityQueryBuilder::create(conn) .sort(&sort) .for_user(user_id) @@ -581,15 +581,17 @@ impl Perform for FollowCommunity { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - client: Client, ) -> Result { let data: &FollowCommunity = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let community_id = data.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; let community_follower_form = CommunityFollowerForm { community_id: data.community_id, user_id: user.id, @@ -598,28 +600,24 @@ impl Perform for FollowCommunity { if community.local { if data.follow { let follow = move |conn: &'_ _| CommunityFollower::follow(conn, &community_follower_form); - if blocking(pool, follow).await?.is_err() { + if blocking(context.pool(), follow).await?.is_err() { return Err(APIError::err("community_follower_already_exists").into()); } } else { let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form); - if blocking(pool, unfollow).await?.is_err() { + if blocking(context.pool(), unfollow).await?.is_err() { return Err(APIError::err("community_follower_already_exists").into()); } } } else if data.follow { // Dont actually add to the community followers here, because you need // to wait for the accept - user - .send_follow(&community.actor_id()?, &client, pool) - .await?; + user.send_follow(&community.actor_id()?, context).await?; } else { - user - .send_unfollow(&community.actor_id()?, &client, pool) - .await?; + user.send_unfollow(&community.actor_id()?, context).await?; let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form); - if blocking(pool, unfollow).await?.is_err() { + if blocking(context.pool(), unfollow).await?.is_err() { return Err(APIError::err("community_follower_already_exists").into()); } } @@ -627,7 +625,7 @@ impl Perform for FollowCommunity { let community_id = data.community_id; let user_id = user.id; - let community_view = blocking(pool, move |conn| { + let community_view = blocking(context.pool(), move |conn| { CommunityView::read(conn, community_id, Some(user_id)) }) .await??; @@ -644,15 +642,14 @@ impl Perform for GetFollowedCommunities { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &GetFollowedCommunities = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let user_id = user.id; - let communities = match blocking(pool, move |conn| { + let communities = match blocking(context.pool(), move |conn| { CommunityFollowerView::for_user(conn, user_id) }) .await? @@ -672,18 +669,17 @@ impl Perform for BanFromCommunity { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - _client: Client, ) -> Result { let data: &BanFromCommunity = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let community_id = data.community_id; let banned_user_id = data.user_id; // Verify that only mods or admins can ban - is_mod_or_admin(pool, user.id, community_id).await?; + is_mod_or_admin(context.pool(), user.id, community_id).await?; let community_user_ban_form = CommunityUserBanForm { community_id: data.community_id, @@ -692,12 +688,12 @@ impl Perform for BanFromCommunity { if data.ban { let ban = move |conn: &'_ _| CommunityUserBan::ban(conn, &community_user_ban_form); - if blocking(pool, ban).await?.is_err() { + if blocking(context.pool(), ban).await?.is_err() { return Err(APIError::err("community_user_already_banned").into()); } } else { let unban = move |conn: &'_ _| CommunityUserBan::unban(conn, &community_user_ban_form); - if blocking(pool, unban).await?.is_err() { + if blocking(context.pool(), unban).await?.is_err() { return Err(APIError::err("community_user_already_banned").into()); } } @@ -705,14 +701,14 @@ impl Perform for BanFromCommunity { // Remove/Restore their data if that's desired if let Some(remove_data) = data.remove_data { // Posts - blocking(pool, move |conn: &'_ _| { + blocking(context.pool(), move |conn: &'_ _| { Post::update_removed_for_creator(conn, banned_user_id, Some(community_id), remove_data) }) .await??; // Comments // Diesel doesn't allow updates with joins, so this has to be a loop - let comments = blocking(pool, move |conn| { + let comments = blocking(context.pool(), move |conn| { CommentQueryBuilder::create(conn) .for_creator_id(banned_user_id) .for_community_id(community_id) @@ -723,7 +719,7 @@ impl Perform for BanFromCommunity { for comment in &comments { let comment_id = comment.id; - blocking(pool, move |conn: &'_ _| { + blocking(context.pool(), move |conn: &'_ _| { Comment::update_removed(conn, comment_id, remove_data) }) .await??; @@ -745,10 +741,16 @@ impl Perform for BanFromCommunity { banned: Some(data.ban), expires, }; - blocking(pool, move |conn| ModBanFromCommunity::create(conn, &form)).await??; + blocking(context.pool(), move |conn| { + ModBanFromCommunity::create(conn, &form) + }) + .await??; let user_id = data.user_id; - let user_view = blocking(pool, move |conn| UserView::get_user_secure(conn, user_id)).await??; + let user_view = blocking(context.pool(), move |conn| { + UserView::get_user_secure(conn, user_id) + }) + .await??; let res = BanFromCommunityResponse { user: user_view, @@ -774,12 +776,11 @@ impl Perform for AddModToCommunity { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - _client: Client, ) -> Result { let data: &AddModToCommunity = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let community_moderator_form = CommunityModeratorForm { community_id: data.community_id, @@ -789,16 +790,16 @@ impl Perform for AddModToCommunity { let community_id = data.community_id; // Verify that only mods or admins can add mod - is_mod_or_admin(pool, user.id, community_id).await?; + is_mod_or_admin(context.pool(), user.id, community_id).await?; if data.added { let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form); - if blocking(pool, join).await?.is_err() { + if blocking(context.pool(), join).await?.is_err() { return Err(APIError::err("community_moderator_already_exists").into()); } } else { let leave = move |conn: &'_ _| CommunityModerator::leave(conn, &community_moderator_form); - if blocking(pool, leave).await?.is_err() { + if blocking(context.pool(), leave).await?.is_err() { return Err(APIError::err("community_moderator_already_exists").into()); } } @@ -810,10 +811,13 @@ impl Perform for AddModToCommunity { community_id: data.community_id, removed: Some(!data.added), }; - blocking(pool, move |conn| ModAddCommunity::create(conn, &form)).await??; + blocking(context.pool(), move |conn| { + ModAddCommunity::create(conn, &form) + }) + .await??; let community_id = data.community_id; - let moderators = blocking(pool, move |conn| { + let moderators = blocking(context.pool(), move |conn| { CommunityModeratorView::for_community(conn, community_id) }) .await??; @@ -839,20 +843,24 @@ impl Perform for TransferCommunity { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &TransferCommunity = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let community_id = data.community_id; - let read_community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let read_community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; - let site_creator_id = - blocking(pool, move |conn| Site::read(conn, 1).map(|s| s.creator_id)).await??; + let site_creator_id = blocking(context.pool(), move |conn| { + Site::read(conn, 1).map(|s| s.creator_id) + }) + .await??; - let mut admins = blocking(pool, move |conn| UserView::admins(conn)).await??; + let mut admins = blocking(context.pool(), move |conn| UserView::admins(conn)).await??; let creator_index = admins .iter() @@ -869,13 +877,13 @@ impl Perform for TransferCommunity { let community_id = data.community_id; let new_creator = data.user_id; let update = move |conn: &'_ _| Community::update_creator(conn, community_id, new_creator); - if blocking(pool, update).await?.is_err() { + if blocking(context.pool(), update).await?.is_err() { return Err(APIError::err("couldnt_update_community").into()); }; // You also have to re-do the community_moderator table, reordering it. let community_id = data.community_id; - let mut community_mods = blocking(pool, move |conn| { + let mut community_mods = blocking(context.pool(), move |conn| { CommunityModeratorView::for_community(conn, community_id) }) .await??; @@ -887,7 +895,7 @@ impl Perform for TransferCommunity { community_mods.insert(0, creator_user); let community_id = data.community_id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { CommunityModerator::delete_for_community(conn, community_id) }) .await??; @@ -900,7 +908,7 @@ impl Perform for TransferCommunity { }; let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form); - if blocking(pool, join).await?.is_err() { + if blocking(context.pool(), join).await?.is_err() { return Err(APIError::err("community_moderator_already_exists").into()); } } @@ -912,11 +920,14 @@ impl Perform for TransferCommunity { community_id: data.community_id, removed: Some(false), }; - blocking(pool, move |conn| ModAddCommunity::create(conn, &form)).await??; + blocking(context.pool(), move |conn| { + ModAddCommunity::create(conn, &form) + }) + .await??; let community_id = data.community_id; let user_id = user.id; - let community_view = match blocking(pool, move |conn| { + let community_view = match blocking(context.pool(), move |conn| { CommunityView::read(conn, community_id, Some(user_id)) }) .await? @@ -926,7 +937,7 @@ impl Perform for TransferCommunity { }; let community_id = data.community_id; - let moderators = match blocking(pool, move |conn| { + let moderators = match blocking(context.pool(), move |conn| { CommunityModeratorView::for_community(conn, community_id) }) .await? diff --git a/server/src/api/mod.rs b/server/src/api/mod.rs index 01884d384..6fed9d05d 100644 --- a/server/src/api/mod.rs +++ b/server/src/api/mod.rs @@ -1,5 +1,12 @@ -use crate::{api::claims::Claims, blocking, websocket::WebsocketInfo, DbPool, LemmyError}; -use actix_web::client::Client; +use crate::{ + api::claims::Claims, + blocking, + websocket::WebsocketInfo, + DbPool, + LemmyContext, + LemmyError, +}; +use actix_web::web::Data; use lemmy_db::{ community::*, community_view::*, @@ -39,9 +46,8 @@ pub trait Perform { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result; } diff --git a/server/src/api/post.rs b/server/src/api/post.rs index 2b48de7a4..fa3c73be3 100644 --- a/server/src/api/post.rs +++ b/server/src/api/post.rs @@ -17,10 +17,10 @@ use crate::{ UserOperation, WebsocketInfo, }, - DbPool, + LemmyContext, LemmyError, }; -use actix_web::client::Client; +use actix_web::web::Data; use lemmy_db::{ comment_view::*, community_view::*, @@ -145,12 +145,11 @@ impl Perform for CreatePost { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &CreatePost = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; check_slurs(&data.name)?; check_slurs_opt(&data.body)?; @@ -159,7 +158,7 @@ impl Perform for CreatePost { return Err(APIError::err("invalid_post_title").into()); } - check_community_ban(user.id, data.community_id, pool).await?; + check_community_ban(user.id, data.community_id, context.pool()).await?; if let Some(url) = data.url.as_ref() { match Url::parse(url) { @@ -170,7 +169,7 @@ impl Perform for CreatePost { // Fetch Iframely and pictrs cached image let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) = - fetch_iframely_and_pictrs_data(&client, data.url.to_owned()).await; + fetch_iframely_and_pictrs_data(context.client(), data.url.to_owned()).await; let post_form = PostForm { name: data.name.trim().to_owned(), @@ -193,21 +192,22 @@ impl Perform for CreatePost { published: None, }; - let inserted_post = match blocking(pool, move |conn| Post::create(conn, &post_form)).await? { - Ok(post) => post, - Err(e) => { - let err_type = if e.to_string() == "value too long for type character varying(200)" { - "post_title_too_long" - } else { - "couldnt_create_post" - }; + let inserted_post = + match blocking(context.pool(), move |conn| Post::create(conn, &post_form)).await? { + Ok(post) => post, + Err(e) => { + let err_type = if e.to_string() == "value too long for type character varying(200)" { + "post_title_too_long" + } else { + "couldnt_create_post" + }; - return Err(APIError::err(err_type).into()); - } - }; + return Err(APIError::err(err_type).into()); + } + }; let inserted_post_id = inserted_post.id; - let updated_post = match blocking(pool, move |conn| { + let updated_post = match blocking(context.pool(), move |conn| { let apub_id = make_apub_endpoint(EndpointType::Post, &inserted_post_id.to_string()).to_string(); Post::update_ap_id(conn, inserted_post_id, apub_id) @@ -218,7 +218,7 @@ impl Perform for CreatePost { Err(_e) => return Err(APIError::err("couldnt_create_post").into()), }; - updated_post.send_create(&user, &client, pool).await?; + updated_post.send_create(&user, context).await?; // They like their own post by default let like_form = PostLikeForm { @@ -228,15 +228,15 @@ impl Perform for CreatePost { }; let like = move |conn: &'_ _| PostLike::like(conn, &like_form); - if blocking(pool, like).await?.is_err() { + if blocking(context.pool(), like).await?.is_err() { return Err(APIError::err("couldnt_like_post").into()); } - updated_post.send_like(&user, &client, pool).await?; + updated_post.send_like(&user, context).await?; // Refetch the view let inserted_post_id = inserted_post.id; - let post_view = match blocking(pool, move |conn| { + let post_view = match blocking(context.pool(), move |conn| { PostView::read(conn, inserted_post_id, Some(user.id)) }) .await? @@ -265,22 +265,25 @@ impl Perform for GetPost { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - _client: Client, ) -> Result { let data: &GetPost = &self; - let user = get_user_from_jwt_opt(&data.auth, pool).await?; + let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?; let user_id = user.map(|u| u.id); let id = data.id; - let post_view = match blocking(pool, move |conn| PostView::read(conn, id, user_id)).await? { + let post_view = match blocking(context.pool(), move |conn| { + PostView::read(conn, id, user_id) + }) + .await? + { Ok(post) => post, Err(_e) => return Err(APIError::err("couldnt_find_post").into()), }; let id = data.id; - let comments = blocking(pool, move |conn| { + let comments = blocking(context.pool(), move |conn| { CommentQueryBuilder::create(conn) .for_post_id(id) .my_user_id(user_id) @@ -290,13 +293,13 @@ impl Perform for GetPost { .await??; let community_id = post_view.community_id; - let community = blocking(pool, move |conn| { + let community = blocking(context.pool(), move |conn| { CommunityView::read(conn, community_id, user_id) }) .await??; let community_id = post_view.community_id; - let moderators = blocking(pool, move |conn| { + let moderators = blocking(context.pool(), move |conn| { CommunityModeratorView::for_community(conn, community_id) }) .await??; @@ -333,12 +336,11 @@ impl Perform for GetPosts { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - _client: Client, ) -> Result { let data: &GetPosts = &self; - let user = get_user_from_jwt_opt(&data.auth, pool).await?; + let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?; let user_id = match &user { Some(user) => Some(user.id), @@ -357,7 +359,7 @@ impl Perform for GetPosts { let limit = data.limit; let community_id = data.community_id; let community_name = data.community_name.to_owned(); - let posts = match blocking(pool, move |conn| { + let posts = match blocking(context.pool(), move |conn| { PostQueryBuilder::create(conn) .listing_type(type_) .sort(&sort) @@ -399,16 +401,15 @@ impl Perform for CreatePostLike { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &CreatePostLike = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; // Don't do a downvote if site has downvotes disabled if data.score == -1 { - let site = blocking(pool, move |conn| SiteView::read(conn)).await??; + let site = blocking(context.pool(), move |conn| SiteView::read(conn)).await??; if !site.enable_downvotes { return Err(APIError::err("downvotes_disabled").into()); } @@ -416,9 +417,9 @@ impl Perform for CreatePostLike { // Check for a community ban let post_id = data.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; - check_community_ban(user.id, post.community_id, pool).await?; + check_community_ban(user.id, post.community_id, context.pool()).await?; let like_form = PostLikeForm { post_id: data.post_id, @@ -428,29 +429,32 @@ impl Perform for CreatePostLike { // Remove any likes first let user_id = user.id; - blocking(pool, move |conn| PostLike::remove(conn, user_id, post_id)).await??; + blocking(context.pool(), move |conn| { + PostLike::remove(conn, user_id, post_id) + }) + .await??; // Only add the like if the score isnt 0 let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1); if do_add { let like_form2 = like_form.clone(); let like = move |conn: &'_ _| PostLike::like(conn, &like_form2); - if blocking(pool, like).await?.is_err() { + if blocking(context.pool(), like).await?.is_err() { return Err(APIError::err("couldnt_like_post").into()); } if like_form.score == 1 { - post.send_like(&user, &client, pool).await?; + post.send_like(&user, context).await?; } else if like_form.score == -1 { - post.send_dislike(&user, &client, pool).await?; + post.send_dislike(&user, context).await?; } } else { - post.send_undo_like(&user, &client, pool).await?; + post.send_undo_like(&user, context).await?; } let post_id = data.post_id; let user_id = user.id; - let post_view = match blocking(pool, move |conn| { + let post_view = match blocking(context.pool(), move |conn| { PostView::read(conn, post_id, Some(user_id)) }) .await? @@ -479,12 +483,11 @@ impl Perform for EditPost { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &EditPost = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; check_slurs(&data.name)?; check_slurs_opt(&data.body)?; @@ -494,9 +497,9 @@ impl Perform for EditPost { } let edit_id = data.edit_id; - let orig_post = blocking(pool, move |conn| Post::read(conn, edit_id)).await??; + let orig_post = blocking(context.pool(), move |conn| Post::read(conn, edit_id)).await??; - check_community_ban(user.id, orig_post.community_id, pool).await?; + check_community_ban(user.id, orig_post.community_id, context.pool()).await?; // Verify that only the creator can edit if !Post::is_post_creator(user.id, orig_post.creator_id) { @@ -505,7 +508,7 @@ impl Perform for EditPost { // Fetch Iframely and Pictrs cached image let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) = - fetch_iframely_and_pictrs_data(&client, data.url.to_owned()).await; + fetch_iframely_and_pictrs_data(context.client(), data.url.to_owned()).await; let post_form = PostForm { name: data.name.trim().to_owned(), @@ -529,7 +532,10 @@ impl Perform for EditPost { }; let edit_id = data.edit_id; - let res = blocking(pool, move |conn| Post::update(conn, edit_id, &post_form)).await?; + let res = blocking(context.pool(), move |conn| { + Post::update(conn, edit_id, &post_form) + }) + .await?; let updated_post: Post = match res { Ok(post) => post, Err(e) => { @@ -544,10 +550,10 @@ impl Perform for EditPost { }; // Send apub update - updated_post.send_update(&user, &client, pool).await?; + updated_post.send_update(&user, context).await?; let edit_id = data.edit_id; - let post_view = blocking(pool, move |conn| { + let post_view = blocking(context.pool(), move |conn| { PostView::read(conn, edit_id, Some(user.id)) }) .await??; @@ -572,17 +578,16 @@ impl Perform for DeletePost { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &DeletePost = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let edit_id = data.edit_id; - let orig_post = blocking(pool, move |conn| Post::read(conn, edit_id)).await??; + let orig_post = blocking(context.pool(), move |conn| Post::read(conn, edit_id)).await??; - check_community_ban(user.id, orig_post.community_id, pool).await?; + check_community_ban(user.id, orig_post.community_id, context.pool()).await?; // Verify that only the creator can delete if !Post::is_post_creator(user.id, orig_post.creator_id) { @@ -592,21 +597,21 @@ impl Perform for DeletePost { // Update the post let edit_id = data.edit_id; let deleted = data.deleted; - let updated_post = blocking(pool, move |conn| { + let updated_post = blocking(context.pool(), move |conn| { Post::update_deleted(conn, edit_id, deleted) }) .await??; // apub updates if deleted { - updated_post.send_delete(&user, &client, pool).await?; + updated_post.send_delete(&user, context).await?; } else { - updated_post.send_undo_delete(&user, &client, pool).await?; + updated_post.send_undo_delete(&user, context).await?; } // Refetch the post let edit_id = data.edit_id; - let post_view = blocking(pool, move |conn| { + let post_view = blocking(context.pool(), move |conn| { PostView::read(conn, edit_id, Some(user.id)) }) .await??; @@ -631,25 +636,24 @@ impl Perform for RemovePost { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &RemovePost = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let edit_id = data.edit_id; - let orig_post = blocking(pool, move |conn| Post::read(conn, edit_id)).await??; + let orig_post = blocking(context.pool(), move |conn| Post::read(conn, edit_id)).await??; - check_community_ban(user.id, orig_post.community_id, pool).await?; + check_community_ban(user.id, orig_post.community_id, context.pool()).await?; // Verify that only the mods can remove - is_mod_or_admin(pool, user.id, orig_post.community_id).await?; + is_mod_or_admin(context.pool(), user.id, orig_post.community_id).await?; // Update the post let edit_id = data.edit_id; let removed = data.removed; - let updated_post = blocking(pool, move |conn| { + let updated_post = blocking(context.pool(), move |conn| { Post::update_removed(conn, edit_id, removed) }) .await??; @@ -661,19 +665,22 @@ impl Perform for RemovePost { removed: Some(removed), reason: data.reason.to_owned(), }; - blocking(pool, move |conn| ModRemovePost::create(conn, &form)).await??; + blocking(context.pool(), move |conn| { + ModRemovePost::create(conn, &form) + }) + .await??; // apub updates if removed { - updated_post.send_remove(&user, &client, pool).await?; + updated_post.send_remove(&user, context).await?; } else { - updated_post.send_undo_remove(&user, &client, pool).await?; + updated_post.send_undo_remove(&user, context).await?; } // Refetch the post let edit_id = data.edit_id; let user_id = user.id; - let post_view = blocking(pool, move |conn| { + let post_view = blocking(context.pool(), move |conn| { PostView::read(conn, edit_id, Some(user_id)) }) .await??; @@ -698,26 +705,27 @@ impl Perform for LockPost { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &LockPost = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let edit_id = data.edit_id; - let orig_post = blocking(pool, move |conn| Post::read(conn, edit_id)).await??; + let orig_post = blocking(context.pool(), move |conn| Post::read(conn, edit_id)).await??; - check_community_ban(user.id, orig_post.community_id, pool).await?; + check_community_ban(user.id, orig_post.community_id, context.pool()).await?; // Verify that only the mods can lock - is_mod_or_admin(pool, user.id, orig_post.community_id).await?; + is_mod_or_admin(context.pool(), user.id, orig_post.community_id).await?; // Update the post let edit_id = data.edit_id; let locked = data.locked; - let updated_post = - blocking(pool, move |conn| Post::update_locked(conn, edit_id, locked)).await??; + let updated_post = blocking(context.pool(), move |conn| { + Post::update_locked(conn, edit_id, locked) + }) + .await??; // Mod tables let form = ModLockPostForm { @@ -725,14 +733,14 @@ impl Perform for LockPost { post_id: data.edit_id, locked: Some(locked), }; - blocking(pool, move |conn| ModLockPost::create(conn, &form)).await??; + blocking(context.pool(), move |conn| ModLockPost::create(conn, &form)).await??; // apub updates - updated_post.send_update(&user, &client, pool).await?; + updated_post.send_update(&user, context).await?; // Refetch the post let edit_id = data.edit_id; - let post_view = blocking(pool, move |conn| { + let post_view = blocking(context.pool(), move |conn| { PostView::read(conn, edit_id, Some(user.id)) }) .await??; @@ -757,25 +765,24 @@ impl Perform for StickyPost { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &StickyPost = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let edit_id = data.edit_id; - let orig_post = blocking(pool, move |conn| Post::read(conn, edit_id)).await??; + let orig_post = blocking(context.pool(), move |conn| Post::read(conn, edit_id)).await??; - check_community_ban(user.id, orig_post.community_id, pool).await?; + check_community_ban(user.id, orig_post.community_id, context.pool()).await?; // Verify that only the mods can sticky - is_mod_or_admin(pool, user.id, orig_post.community_id).await?; + is_mod_or_admin(context.pool(), user.id, orig_post.community_id).await?; // Update the post let edit_id = data.edit_id; let stickied = data.stickied; - let updated_post = blocking(pool, move |conn| { + let updated_post = blocking(context.pool(), move |conn| { Post::update_stickied(conn, edit_id, stickied) }) .await??; @@ -786,15 +793,18 @@ impl Perform for StickyPost { post_id: data.edit_id, stickied: Some(stickied), }; - blocking(pool, move |conn| ModStickyPost::create(conn, &form)).await??; + blocking(context.pool(), move |conn| { + ModStickyPost::create(conn, &form) + }) + .await??; // Apub updates // TODO stickied should pry work like locked for ease of use - updated_post.send_update(&user, &client, pool).await?; + updated_post.send_update(&user, context).await?; // Refetch the post let edit_id = data.edit_id; - let post_view = blocking(pool, move |conn| { + let post_view = blocking(context.pool(), move |conn| { PostView::read(conn, edit_id, Some(user.id)) }) .await??; @@ -819,12 +829,11 @@ impl Perform for SavePost { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &SavePost = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let post_saved_form = PostSavedForm { post_id: data.post_id, @@ -833,19 +842,19 @@ impl Perform for SavePost { if data.save { let save = move |conn: &'_ _| PostSaved::save(conn, &post_saved_form); - if blocking(pool, save).await?.is_err() { + if blocking(context.pool(), save).await?.is_err() { return Err(APIError::err("couldnt_save_post").into()); } } else { let unsave = move |conn: &'_ _| PostSaved::unsave(conn, &post_saved_form); - if blocking(pool, unsave).await?.is_err() { + if blocking(context.pool(), unsave).await?.is_err() { return Err(APIError::err("couldnt_save_post").into()); } } let post_id = data.post_id; let user_id = user.id; - let post_view = blocking(pool, move |conn| { + let post_view = blocking(context.pool(), move |conn| { PostView::read(conn, post_id, Some(user_id)) }) .await??; diff --git a/server/src/api/site.rs b/server/src/api/site.rs index 12c59cca3..a9e393d8a 100644 --- a/server/src/api/site.rs +++ b/server/src/api/site.rs @@ -17,10 +17,10 @@ use crate::{ UserOperation, WebsocketInfo, }, - DbPool, + LemmyContext, LemmyError, }; -use actix_web::client::Client; +use actix_web::web::Data; use anyhow::Context; use lemmy_db::{ category::*, @@ -166,13 +166,12 @@ impl Perform for ListCategories { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let _data: &ListCategories = &self; - let categories = blocking(pool, move |conn| Category::list_all(conn)).await??; + let categories = blocking(context.pool(), move |conn| Category::list_all(conn)).await??; // Return the jwt Ok(ListCategoriesResponse { categories }) @@ -185,9 +184,8 @@ impl Perform for GetModlog { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &GetModlog = &self; @@ -195,39 +193,39 @@ impl Perform for GetModlog { let mod_user_id = data.mod_user_id; let page = data.page; let limit = data.limit; - let removed_posts = blocking(pool, move |conn| { + let removed_posts = blocking(context.pool(), move |conn| { ModRemovePostView::list(conn, community_id, mod_user_id, page, limit) }) .await??; - let locked_posts = blocking(pool, move |conn| { + let locked_posts = blocking(context.pool(), move |conn| { ModLockPostView::list(conn, community_id, mod_user_id, page, limit) }) .await??; - let stickied_posts = blocking(pool, move |conn| { + let stickied_posts = blocking(context.pool(), move |conn| { ModStickyPostView::list(conn, community_id, mod_user_id, page, limit) }) .await??; - let removed_comments = blocking(pool, move |conn| { + let removed_comments = blocking(context.pool(), move |conn| { ModRemoveCommentView::list(conn, community_id, mod_user_id, page, limit) }) .await??; - let banned_from_community = blocking(pool, move |conn| { + let banned_from_community = blocking(context.pool(), move |conn| { ModBanFromCommunityView::list(conn, community_id, mod_user_id, page, limit) }) .await??; - let added_to_community = blocking(pool, move |conn| { + let added_to_community = blocking(context.pool(), move |conn| { ModAddCommunityView::list(conn, community_id, mod_user_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(pool, move |conn| { + blocking(context.pool(), move |conn| { Ok(( ModRemoveCommunityView::list(conn, mod_user_id, page, limit)?, ModBanView::list(conn, mod_user_id, page, limit)?, @@ -260,19 +258,18 @@ impl Perform for CreateSite { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &CreateSite = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; check_slurs(&data.name)?; check_slurs_opt(&data.description)?; // Make sure user is an admin - is_admin(pool, user.id).await?; + is_admin(context.pool(), user.id).await?; let site_form = SiteForm { name: data.name.to_owned(), @@ -287,11 +284,11 @@ impl Perform for CreateSite { }; let create_site = move |conn: &'_ _| Site::create(conn, &site_form); - if blocking(pool, create_site).await?.is_err() { + if blocking(context.pool(), create_site).await?.is_err() { return Err(APIError::err("site_already_exists").into()); } - let site_view = blocking(pool, move |conn| SiteView::read(conn)).await??; + let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??; Ok(SiteResponse { site: site_view }) } @@ -302,20 +299,19 @@ impl Perform for EditSite { type Response = SiteResponse; async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - _client: Client, ) -> Result { let data: &EditSite = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; check_slurs(&data.name)?; check_slurs_opt(&data.description)?; // Make sure user is an admin - is_admin(pool, user.id).await?; + is_admin(context.pool(), user.id).await?; - let found_site = blocking(pool, move |conn| Site::read(conn, 1)).await??; + let found_site = blocking(context.pool(), move |conn| Site::read(conn, 1)).await??; let icon = diesel_option_overwrite(&data.icon); let banner = diesel_option_overwrite(&data.banner); @@ -333,11 +329,11 @@ impl Perform for EditSite { }; let update_site = move |conn: &'_ _| Site::update(conn, 1, &site_form); - if blocking(pool, update_site).await?.is_err() { + if blocking(context.pool(), update_site).await?.is_err() { return Err(APIError::err("couldnt_update_site").into()); } - let site_view = blocking(pool, move |conn| SiteView::read(conn)).await??; + let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??; let res = SiteResponse { site: site_view }; @@ -359,16 +355,15 @@ impl Perform for GetSite { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &GetSite = &self; // TODO refactor this a little - let res = blocking(pool, move |conn| Site::read(conn, 1)).await?; + let res = blocking(context.pool(), move |conn| Site::read(conn, 1)).await?; let site_view = if res.is_ok() { - Some(blocking(pool, move |conn| SiteView::read(conn)).await??) + Some(blocking(context.pool(), move |conn| SiteView::read(conn)).await??) } else if let Some(setup) = Settings::get().setup.as_ref() { let register = Register { username: setup.admin_username.to_owned(), @@ -380,9 +375,7 @@ impl Perform for GetSite { captcha_uuid: None, captcha_answer: None, }; - let login_response = register - .perform(pool, websocket_info.clone(), client.clone()) - .await?; + let login_response = register.perform(context, websocket_info.clone()).await?; info!("Admin {} created", setup.admin_username); let create_site = CreateSite { @@ -395,16 +388,14 @@ impl Perform for GetSite { enable_nsfw: true, auth: login_response.jwt, }; - create_site - .perform(pool, websocket_info.clone(), client.clone()) - .await?; + create_site.perform(context, websocket_info.clone()).await?; info!("Site {} created", setup.site_name); - Some(blocking(pool, move |conn| SiteView::read(conn)).await??) + Some(blocking(context.pool(), move |conn| SiteView::read(conn)).await??) } else { None }; - let mut admins = blocking(pool, move |conn| UserView::admins(conn)).await??; + let mut admins = blocking(context.pool(), move |conn| UserView::admins(conn)).await??; // Make sure the site creator is the top admin if let Some(site_view) = site_view.to_owned() { @@ -417,7 +408,7 @@ impl Perform for GetSite { } } - let banned = blocking(pool, move |conn| UserView::banned(conn)).await??; + let banned = blocking(context.pool(), move |conn| UserView::banned(conn)).await??; let online = if let Some(ws) = websocket_info { ws.chatserver.send(GetUsersOnline).await.unwrap_or(1) @@ -425,12 +416,14 @@ impl Perform for GetSite { 0 }; - let my_user = get_user_from_jwt_opt(&data.auth, pool).await?.map(|mut u| { - u.password_encrypted = "".to_string(); - u.private_key = None; - u.public_key = None; - u - }); + let my_user = get_user_from_jwt_opt(&data.auth, context.pool()) + .await? + .map(|mut u| { + u.password_encrypted = "".to_string(); + u.private_key = None; + u.public_key = None; + u + }); Ok(GetSiteResponse { site: site_view, @@ -450,20 +443,19 @@ impl Perform for Search { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - client: Client, ) -> Result { let data: &Search = &self; dbg!(&data); - match search_by_apub_id(&data.q, &client, pool).await { + match search_by_apub_id(&data.q, context).await { Ok(r) => return Ok(r), Err(e) => debug!("Failed to resolve search query as activitypub ID: {}", e), } - let user = get_user_from_jwt_opt(&data.auth, pool).await?; + let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?; let user_id = user.map(|u| u.id); let type_ = SearchType::from_str(&data.type_)?; @@ -482,7 +474,7 @@ impl Perform for Search { let community_id = data.community_id; match type_ { SearchType::Posts => { - posts = blocking(pool, move |conn| { + posts = blocking(context.pool(), move |conn| { PostQueryBuilder::create(conn) .sort(&sort) .show_nsfw(true) @@ -496,7 +488,7 @@ impl Perform for Search { .await??; } SearchType::Comments => { - comments = blocking(pool, move |conn| { + comments = blocking(context.pool(), move |conn| { CommentQueryBuilder::create(&conn) .sort(&sort) .search_term(q) @@ -508,7 +500,7 @@ impl Perform for Search { .await??; } SearchType::Communities => { - communities = blocking(pool, move |conn| { + communities = blocking(context.pool(), move |conn| { CommunityQueryBuilder::create(conn) .sort(&sort) .search_term(q) @@ -519,7 +511,7 @@ impl Perform for Search { .await??; } SearchType::Users => { - users = blocking(pool, move |conn| { + users = blocking(context.pool(), move |conn| { UserQueryBuilder::create(conn) .sort(&sort) .search_term(q) @@ -530,7 +522,7 @@ impl Perform for Search { .await??; } SearchType::All => { - posts = blocking(pool, move |conn| { + posts = blocking(context.pool(), move |conn| { PostQueryBuilder::create(conn) .sort(&sort) .show_nsfw(true) @@ -546,7 +538,7 @@ impl Perform for Search { let q = data.q.to_owned(); let sort = SortType::from_str(&data.sort)?; - comments = blocking(pool, move |conn| { + comments = blocking(context.pool(), move |conn| { CommentQueryBuilder::create(conn) .sort(&sort) .search_term(q) @@ -560,7 +552,7 @@ impl Perform for Search { let q = data.q.to_owned(); let sort = SortType::from_str(&data.sort)?; - communities = blocking(pool, move |conn| { + communities = blocking(context.pool(), move |conn| { CommunityQueryBuilder::create(conn) .sort(&sort) .search_term(q) @@ -573,7 +565,7 @@ impl Perform for Search { let q = data.q.to_owned(); let sort = SortType::from_str(&data.sort)?; - users = blocking(pool, move |conn| { + users = blocking(context.pool(), move |conn| { UserQueryBuilder::create(conn) .sort(&sort) .search_term(q) @@ -584,7 +576,7 @@ impl Perform for Search { .await??; } SearchType::Url => { - posts = blocking(pool, move |conn| { + posts = blocking(context.pool(), move |conn| { PostQueryBuilder::create(conn) .sort(&sort) .show_nsfw(true) @@ -615,19 +607,18 @@ impl Perform for TransferSite { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &TransferSite = &self; - let mut user = get_user_from_jwt(&data.auth, pool).await?; + let mut user = get_user_from_jwt(&data.auth, context.pool()).await?; // TODO add a User_::read_safe() for this. user.password_encrypted = "".to_string(); user.private_key = None; user.public_key = None; - let read_site = blocking(pool, move |conn| Site::read(conn, 1)).await??; + let read_site = blocking(context.pool(), move |conn| Site::read(conn, 1)).await??; // Make sure user is the creator if read_site.creator_id != user.id { @@ -636,7 +627,7 @@ impl Perform for TransferSite { let new_creator_id = data.user_id; let transfer_site = move |conn: &'_ _| Site::transfer(conn, new_creator_id); - if blocking(pool, transfer_site).await?.is_err() { + if blocking(context.pool(), transfer_site).await?.is_err() { return Err(APIError::err("couldnt_update_site").into()); }; @@ -647,11 +638,11 @@ impl Perform for TransferSite { removed: Some(false), }; - blocking(pool, move |conn| ModAdd::create(conn, &form)).await??; + blocking(context.pool(), move |conn| ModAdd::create(conn, &form)).await??; - let site_view = blocking(pool, move |conn| SiteView::read(conn)).await??; + let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??; - let mut admins = blocking(pool, move |conn| UserView::admins(conn)).await??; + let mut admins = blocking(context.pool(), move |conn| UserView::admins(conn)).await??; let creator_index = admins .iter() .position(|r| r.id == site_view.creator_id) @@ -659,7 +650,7 @@ impl Perform for TransferSite { let creator_user = admins.remove(creator_index); admins.insert(0, creator_user); - let banned = blocking(pool, move |conn| UserView::banned(conn)).await??; + let banned = blocking(context.pool(), move |conn| UserView::banned(conn)).await??; Ok(GetSiteResponse { site: Some(site_view), @@ -679,15 +670,14 @@ impl Perform for GetSiteConfig { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &GetSiteConfig = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; // Only let admins read this - is_admin(pool, user.id).await?; + is_admin(context.pool(), user.id).await?; let config_hjson = Settings::read_config_file()?; @@ -701,15 +691,14 @@ impl Perform for SaveSiteConfig { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &SaveSiteConfig = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; // Only let admins read this - let admins = blocking(pool, move |conn| UserView::admins(conn)).await??; + let admins = blocking(context.pool(), move |conn| UserView::admins(conn)).await??; let admin_ids: Vec = admins.into_iter().map(|m| m.id).collect(); if !admin_ids.contains(&user.id) { diff --git a/server/src/api/user.rs b/server/src/api/user.rs index bbb8d482b..a84b89873 100644 --- a/server/src/api/user.rs +++ b/server/src/api/user.rs @@ -16,10 +16,10 @@ use crate::{ UserOperation, WebsocketInfo, }, - DbPool, + LemmyContext, LemmyError, }; -use actix_web::client::Client; +use actix_web::web::Data; use anyhow::Context; use bcrypt::verify; use captcha::{gen, Difficulty}; @@ -302,15 +302,14 @@ impl Perform for Login { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &Login = &self; // Fetch that username / email let username_or_email = data.username_or_email.clone(); - let user = match blocking(pool, move |conn| { + let user = match blocking(context.pool(), move |conn| { User_::find_by_email_or_username(conn, &username_or_email) }) .await? @@ -338,14 +337,13 @@ impl Perform for Register { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - _client: Client, ) -> Result { let data: &Register = &self; // Make sure site has open registration - if let Ok(site) = blocking(pool, move |conn| SiteView::read(conn)).await? { + if let Ok(site) = blocking(context.pool(), move |conn| SiteView::read(conn)).await? { let site: SiteView = site; if !site.open_registration { return Err(APIError::err("registration_closed").into()); @@ -385,7 +383,7 @@ impl Perform for Register { check_slurs(&data.username)?; // Make sure there are no admins - let any_admins = blocking(pool, move |conn| { + let any_admins = blocking(context.pool(), move |conn| { UserView::admins(conn).map(|a| a.is_empty()) }) .await??; @@ -426,7 +424,11 @@ impl Perform for Register { }; // Create the user - let inserted_user = match blocking(pool, move |conn| User_::register(conn, &user_form)).await? { + let inserted_user = match blocking(context.pool(), move |conn| { + User_::register(conn, &user_form) + }) + .await? + { Ok(user) => user, Err(e) => { let err_type = if e.to_string() @@ -444,7 +446,9 @@ impl Perform for Register { let main_community_keypair = generate_actor_keypair()?; // Create the main community if it doesn't exist - let main_community = match blocking(pool, move |conn| Community::read(conn, 2)).await? { + let main_community = match blocking(context.pool(), move |conn| Community::read(conn, 2)) + .await? + { Ok(c) => c, Err(_e) => { let default_community_name = "main"; @@ -467,7 +471,10 @@ impl Perform for Register { icon: None, banner: None, }; - blocking(pool, move |conn| Community::create(conn, &community_form)).await?? + blocking(context.pool(), move |conn| { + Community::create(conn, &community_form) + }) + .await?? } }; @@ -478,7 +485,7 @@ impl Perform for Register { }; let follow = move |conn: &'_ _| CommunityFollower::follow(conn, &community_follower_form); - if blocking(pool, follow).await?.is_err() { + if blocking(context.pool(), follow).await?.is_err() { return Err(APIError::err("community_follower_already_exists").into()); }; @@ -490,7 +497,7 @@ impl Perform for Register { }; let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form); - if blocking(pool, join).await?.is_err() { + if blocking(context.pool(), join).await?.is_err() { return Err(APIError::err("community_moderator_already_exists").into()); } } @@ -508,9 +515,8 @@ impl Perform for GetCaptcha { async fn perform( &self, - _pool: &DbPool, + _context: &Data, websocket_info: Option, - _client: Client, ) -> Result { let captcha_settings = Settings::get().captcha; @@ -557,15 +563,14 @@ impl Perform for SaveUserSettings { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &SaveUserSettings = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let user_id = user.id; - let read_user = blocking(pool, move |conn| User_::read(conn, user_id)).await??; + let read_user = blocking(context.pool(), move |conn| User_::read(conn, user_id)).await??; let bio = match &data.bio { Some(bio) => { @@ -611,7 +616,7 @@ impl Perform for SaveUserSettings { return Err(APIError::err("password_incorrect").into()); } let new_password = new_password.to_owned(); - let user = blocking(pool, move |conn| { + let user = blocking(context.pool(), move |conn| { User_::update_password(conn, user_id, &new_password) }) .await??; @@ -652,7 +657,10 @@ impl Perform for SaveUserSettings { last_refreshed_at: None, }; - let res = blocking(pool, move |conn| User_::update(conn, user_id, &user_form)).await?; + let res = blocking(context.pool(), move |conn| { + User_::update(conn, user_id, &user_form) + }) + .await?; let updated_user: User_ = match res { Ok(user) => user, Err(e) => { @@ -681,12 +689,11 @@ impl Perform for GetUserDetails { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &GetUserDetails = &self; - let user = get_user_from_jwt_opt(&data.auth, pool).await?; + let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?; let show_nsfw = match &user { Some(user) => user.show_nsfw, @@ -702,7 +709,10 @@ impl Perform for GetUserDetails { let user_details_id = match data.user_id { Some(id) => id, None => { - let user = blocking(pool, move |conn| User_::read_from_name(conn, &username)).await?; + let user = blocking(context.pool(), move |conn| { + User_::read_from_name(conn, &username) + }) + .await?; match user { Ok(user) => user.id, Err(_e) => return Err(APIError::err("couldnt_find_that_username_or_email").into()), @@ -710,7 +720,7 @@ impl Perform for GetUserDetails { } }; - let user_view = blocking(pool, move |conn| { + let user_view = blocking(context.pool(), move |conn| { UserView::get_user_secure(conn, user_details_id) }) .await??; @@ -720,7 +730,7 @@ impl Perform for GetUserDetails { let saved_only = data.saved_only; let community_id = data.community_id; let user_id = user.map(|u| u.id); - let (posts, comments) = blocking(pool, move |conn| { + let (posts, comments) = blocking(context.pool(), move |conn| { let mut posts_query = PostQueryBuilder::create(conn) .sort(&sort) .show_nsfw(show_nsfw) @@ -751,11 +761,11 @@ impl Perform for GetUserDetails { }) .await??; - let follows = blocking(pool, move |conn| { + let follows = blocking(context.pool(), move |conn| { CommunityFollowerView::for_user(conn, user_details_id) }) .await??; - let moderates = blocking(pool, move |conn| { + let moderates = blocking(context.pool(), move |conn| { CommunityModeratorView::for_user(conn, user_details_id) }) .await??; @@ -777,20 +787,19 @@ impl Perform for AddAdmin { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - _client: Client, ) -> Result { let data: &AddAdmin = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; // Make sure user is an admin - is_admin(pool, user.id).await?; + is_admin(context.pool(), user.id).await?; let added = data.added; let added_user_id = data.user_id; let add_admin = move |conn: &'_ _| User_::add_admin(conn, added_user_id, added); - if blocking(pool, add_admin).await?.is_err() { + if blocking(context.pool(), add_admin).await?.is_err() { return Err(APIError::err("couldnt_update_user").into()); } @@ -801,12 +810,14 @@ impl Perform for AddAdmin { removed: Some(!data.added), }; - blocking(pool, move |conn| ModAdd::create(conn, &form)).await??; + blocking(context.pool(), move |conn| ModAdd::create(conn, &form)).await??; - let site_creator_id = - blocking(pool, move |conn| Site::read(conn, 1).map(|s| s.creator_id)).await??; + let site_creator_id = blocking(context.pool(), move |conn| { + Site::read(conn, 1).map(|s| s.creator_id) + }) + .await??; - let mut admins = blocking(pool, move |conn| UserView::admins(conn)).await??; + let mut admins = blocking(context.pool(), move |conn| UserView::admins(conn)).await??; let creator_index = admins .iter() .position(|r| r.id == site_creator_id) @@ -834,39 +845,38 @@ impl Perform for BanUser { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - _client: Client, ) -> Result { let data: &BanUser = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; // Make sure user is an admin - is_admin(pool, user.id).await?; + is_admin(context.pool(), user.id).await?; let ban = data.ban; let banned_user_id = data.user_id; let ban_user = move |conn: &'_ _| User_::ban_user(conn, banned_user_id, ban); - if blocking(pool, ban_user).await?.is_err() { + if blocking(context.pool(), ban_user).await?.is_err() { return Err(APIError::err("couldnt_update_user").into()); } // Remove their data if that's desired if let Some(remove_data) = data.remove_data { // Posts - blocking(pool, move |conn: &'_ _| { + blocking(context.pool(), move |conn: &'_ _| { Post::update_removed_for_creator(conn, banned_user_id, None, remove_data) }) .await??; // Communities - blocking(pool, move |conn: &'_ _| { + blocking(context.pool(), move |conn: &'_ _| { Community::update_removed_for_creator(conn, banned_user_id, remove_data) }) .await??; // Comments - blocking(pool, move |conn: &'_ _| { + blocking(context.pool(), move |conn: &'_ _| { Comment::update_removed_for_creator(conn, banned_user_id, remove_data) }) .await??; @@ -886,10 +896,13 @@ impl Perform for BanUser { expires, }; - blocking(pool, move |conn| ModBan::create(conn, &form)).await??; + blocking(context.pool(), move |conn| ModBan::create(conn, &form)).await??; let user_id = data.user_id; - let user_view = blocking(pool, move |conn| UserView::get_user_secure(conn, user_id)).await??; + let user_view = blocking(context.pool(), move |conn| { + UserView::get_user_secure(conn, user_id) + }) + .await??; let res = BanUserResponse { user: user_view, @@ -914,12 +927,11 @@ impl Perform for GetReplies { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &GetReplies = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let sort = SortType::from_str(&data.sort)?; @@ -927,7 +939,7 @@ impl Perform for GetReplies { let limit = data.limit; let unread_only = data.unread_only; let user_id = user.id; - let replies = blocking(pool, move |conn| { + let replies = blocking(context.pool(), move |conn| { ReplyQueryBuilder::create(conn, user_id) .sort(&sort) .unread_only(unread_only) @@ -947,12 +959,11 @@ impl Perform for GetUserMentions { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &GetUserMentions = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let sort = SortType::from_str(&data.sort)?; @@ -960,7 +971,7 @@ impl Perform for GetUserMentions { let limit = data.limit; let unread_only = data.unread_only; let user_id = user.id; - let mentions = blocking(pool, move |conn| { + let mentions = blocking(context.pool(), move |conn| { UserMentionQueryBuilder::create(conn, user_id) .sort(&sort) .unread_only(unread_only) @@ -980,16 +991,17 @@ impl Perform for MarkUserMentionAsRead { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &MarkUserMentionAsRead = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let user_mention_id = data.user_mention_id; - let read_user_mention = - blocking(pool, move |conn| UserMention::read(conn, user_mention_id)).await??; + let read_user_mention = blocking(context.pool(), move |conn| { + UserMention::read(conn, user_mention_id) + }) + .await??; if user.id != read_user_mention.recipient_id { return Err(APIError::err("couldnt_update_comment").into()); @@ -998,13 +1010,13 @@ impl Perform for MarkUserMentionAsRead { let user_mention_id = read_user_mention.id; let read = data.read; let update_mention = move |conn: &'_ _| UserMention::update_read(conn, user_mention_id, read); - if blocking(pool, update_mention).await?.is_err() { + if blocking(context.pool(), update_mention).await?.is_err() { return Err(APIError::err("couldnt_update_comment").into()); }; let user_mention_id = read_user_mention.id; let user_id = user.id; - let user_mention_view = blocking(pool, move |conn| { + let user_mention_view = blocking(context.pool(), move |conn| { UserMentionView::read(conn, user_mention_id, user_id) }) .await??; @@ -1021,15 +1033,14 @@ impl Perform for MarkAllAsRead { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &MarkAllAsRead = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let user_id = user.id; - let replies = blocking(pool, move |conn| { + let replies = blocking(context.pool(), move |conn| { ReplyQueryBuilder::create(conn, user_id) .unread_only(true) .page(1) @@ -1044,20 +1055,23 @@ impl Perform for MarkAllAsRead { for reply in &replies { let reply_id = reply.id; let mark_as_read = move |conn: &'_ _| Comment::update_read(conn, reply_id, true); - if blocking(pool, mark_as_read).await?.is_err() { + if blocking(context.pool(), mark_as_read).await?.is_err() { return Err(APIError::err("couldnt_update_comment").into()); } } // Mark all user mentions as read let update_user_mentions = move |conn: &'_ _| UserMention::mark_all_as_read(conn, user_id); - if blocking(pool, update_user_mentions).await?.is_err() { + if blocking(context.pool(), update_user_mentions) + .await? + .is_err() + { return Err(APIError::err("couldnt_update_comment").into()); } // Mark all private_messages as read let update_pm = move |conn: &'_ _| PrivateMessage::mark_all_as_read(conn, user_id); - if blocking(pool, update_pm).await?.is_err() { + if blocking(context.pool(), update_pm).await?.is_err() { return Err(APIError::err("couldnt_update_private_message").into()); } @@ -1071,12 +1085,11 @@ impl Perform for DeleteAccount { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &DeleteAccount = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; // Verify the password let valid: bool = verify(&data.password, &user.password_encrypted).unwrap_or(false); @@ -1087,13 +1100,13 @@ impl Perform for DeleteAccount { // Comments let user_id = user.id; let permadelete = move |conn: &'_ _| Comment::permadelete_for_creator(conn, user_id); - if blocking(pool, permadelete).await?.is_err() { + if blocking(context.pool(), permadelete).await?.is_err() { return Err(APIError::err("couldnt_update_comment").into()); } // Posts let permadelete = move |conn: &'_ _| Post::permadelete_for_creator(conn, user_id); - if blocking(pool, permadelete).await?.is_err() { + if blocking(context.pool(), permadelete).await?.is_err() { return Err(APIError::err("couldnt_update_post").into()); } @@ -1109,15 +1122,18 @@ impl Perform for PasswordReset { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &PasswordReset = &self; // Fetch that email let email = data.email.clone(); - let user = match blocking(pool, move |conn| User_::find_by_email(conn, &email)).await? { + let user = match blocking(context.pool(), move |conn| { + User_::find_by_email(conn, &email) + }) + .await? + { Ok(user) => user, Err(_e) => return Err(APIError::err("couldnt_find_that_username_or_email").into()), }; @@ -1128,7 +1144,7 @@ impl Perform for PasswordReset { // Insert the row let token2 = token.clone(); let user_id = user.id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { PasswordResetRequest::create_token(conn, user_id, &token2) }) .await??; @@ -1154,15 +1170,14 @@ impl Perform for PasswordChange { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &PasswordChange = &self; // Fetch the user_id from the token let token = data.token.clone(); - let user_id = blocking(pool, move |conn| { + let user_id = blocking(context.pool(), move |conn| { PasswordResetRequest::read_from_token(conn, &token).map(|p| p.user_id) }) .await??; @@ -1174,7 +1189,7 @@ impl Perform for PasswordChange { // Update the user with the new password let password = data.password.clone(); - let updated_user = match blocking(pool, move |conn| { + let updated_user = match blocking(context.pool(), move |conn| { User_::update_password(conn, user_id, &password) }) .await? @@ -1196,12 +1211,11 @@ impl Perform for CreatePrivateMessage { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &CreatePrivateMessage = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let hostname = &format!("https://{}", Settings::get().hostname); @@ -1219,7 +1233,7 @@ impl Perform for CreatePrivateMessage { published: None, }; - let inserted_private_message = match blocking(pool, move |conn| { + let inserted_private_message = match blocking(context.pool(), move |conn| { PrivateMessage::create(conn, &private_message_form) }) .await? @@ -1231,7 +1245,7 @@ impl Perform for CreatePrivateMessage { }; let inserted_private_message_id = inserted_private_message.id; - let updated_private_message = match blocking(pool, move |conn| { + let updated_private_message = match blocking(context.pool(), move |conn| { let apub_id = make_apub_endpoint( EndpointType::PrivateMessage, &inserted_private_message_id.to_string(), @@ -1245,13 +1259,12 @@ impl Perform for CreatePrivateMessage { Err(_e) => return Err(APIError::err("couldnt_create_private_message").into()), }; - updated_private_message - .send_create(&user, &client, pool) - .await?; + updated_private_message.send_create(&user, context).await?; // Send notifications to the recipient let recipient_id = data.recipient_id; - let recipient_user = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??; + let recipient_user = + blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??; if recipient_user.send_notifications_to_email { if let Some(email) = recipient_user.email { let subject = &format!( @@ -1270,7 +1283,7 @@ impl Perform for CreatePrivateMessage { } } - let message = blocking(pool, move |conn| { + let message = blocking(context.pool(), move |conn| { PrivateMessageView::read(conn, inserted_private_message.id) }) .await??; @@ -1296,17 +1309,18 @@ impl Perform for EditPrivateMessage { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &EditPrivateMessage = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; // Checking permissions let edit_id = data.edit_id; - let orig_private_message = - blocking(pool, move |conn| PrivateMessage::read(conn, edit_id)).await??; + let orig_private_message = blocking(context.pool(), move |conn| { + PrivateMessage::read(conn, edit_id) + }) + .await??; if user.id != orig_private_message.creator_id { return Err(APIError::err("no_private_message_edit_allowed").into()); } @@ -1314,7 +1328,7 @@ impl Perform for EditPrivateMessage { // Doing the update let content_slurs_removed = remove_slurs(&data.content); let edit_id = data.edit_id; - let updated_private_message = match blocking(pool, move |conn| { + let updated_private_message = match blocking(context.pool(), move |conn| { PrivateMessage::update_content(conn, edit_id, &content_slurs_removed) }) .await? @@ -1324,12 +1338,13 @@ impl Perform for EditPrivateMessage { }; // Send the apub update - updated_private_message - .send_update(&user, &client, pool) - .await?; + updated_private_message.send_update(&user, context).await?; let edit_id = data.edit_id; - let message = blocking(pool, move |conn| PrivateMessageView::read(conn, edit_id)).await??; + let message = blocking(context.pool(), move |conn| { + PrivateMessageView::read(conn, edit_id) + }) + .await??; let recipient_id = message.recipient_id; let res = PrivateMessageResponse { message }; @@ -1353,17 +1368,18 @@ impl Perform for DeletePrivateMessage { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - client: Client, ) -> Result { let data: &DeletePrivateMessage = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; // Checking permissions let edit_id = data.edit_id; - let orig_private_message = - blocking(pool, move |conn| PrivateMessage::read(conn, edit_id)).await??; + let orig_private_message = blocking(context.pool(), move |conn| { + PrivateMessage::read(conn, edit_id) + }) + .await??; if user.id != orig_private_message.creator_id { return Err(APIError::err("no_private_message_edit_allowed").into()); } @@ -1371,7 +1387,7 @@ impl Perform for DeletePrivateMessage { // Doing the update let edit_id = data.edit_id; let deleted = data.deleted; - let updated_private_message = match blocking(pool, move |conn| { + let updated_private_message = match blocking(context.pool(), move |conn| { PrivateMessage::update_deleted(conn, edit_id, deleted) }) .await? @@ -1382,17 +1398,18 @@ impl Perform for DeletePrivateMessage { // Send the apub update if data.deleted { - updated_private_message - .send_delete(&user, &client, pool) - .await?; + updated_private_message.send_delete(&user, context).await?; } else { updated_private_message - .send_undo_delete(&user, &client, pool) + .send_undo_delete(&user, context) .await?; } let edit_id = data.edit_id; - let message = blocking(pool, move |conn| PrivateMessageView::read(conn, edit_id)).await??; + let message = blocking(context.pool(), move |conn| { + PrivateMessageView::read(conn, edit_id) + }) + .await??; let recipient_id = message.recipient_id; let res = PrivateMessageResponse { message }; @@ -1416,17 +1433,18 @@ impl Perform for MarkPrivateMessageAsRead { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - _client: Client, ) -> Result { let data: &MarkPrivateMessageAsRead = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; // Checking permissions let edit_id = data.edit_id; - let orig_private_message = - blocking(pool, move |conn| PrivateMessage::read(conn, edit_id)).await??; + let orig_private_message = blocking(context.pool(), move |conn| { + PrivateMessage::read(conn, edit_id) + }) + .await??; if user.id != orig_private_message.recipient_id { return Err(APIError::err("couldnt_update_private_message").into()); } @@ -1434,7 +1452,7 @@ impl Perform for MarkPrivateMessageAsRead { // Doing the update let edit_id = data.edit_id; let read = data.read; - match blocking(pool, move |conn| { + match blocking(context.pool(), move |conn| { PrivateMessage::update_read(conn, edit_id, read) }) .await? @@ -1446,7 +1464,10 @@ impl Perform for MarkPrivateMessageAsRead { // No need to send an apub update let edit_id = data.edit_id; - let message = blocking(pool, move |conn| PrivateMessageView::read(conn, edit_id)).await??; + let message = blocking(context.pool(), move |conn| { + PrivateMessageView::read(conn, edit_id) + }) + .await??; let recipient_id = message.recipient_id; let res = PrivateMessageResponse { message }; @@ -1470,18 +1491,17 @@ impl Perform for GetPrivateMessages { async fn perform( &self, - pool: &DbPool, + context: &Data, _websocket_info: Option, - _client: Client, ) -> Result { let data: &GetPrivateMessages = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; let user_id = user.id; let page = data.page; let limit = data.limit; let unread_only = data.unread_only; - let messages = blocking(pool, move |conn| { + let messages = blocking(context.pool(), move |conn| { PrivateMessageQueryBuilder::create(&conn, user_id) .page(page) .limit(limit) @@ -1500,12 +1520,11 @@ impl Perform for UserJoin { async fn perform( &self, - pool: &DbPool, + context: &Data, websocket_info: Option, - _client: Client, ) -> Result { let data: &UserJoin = &self; - let user = get_user_from_jwt(&data.auth, pool).await?; + let user = get_user_from_jwt(&data.auth, context.pool()).await?; if let Some(ws) = websocket_info { if let Some(id) = ws.id { diff --git a/server/src/apub/activities.rs b/server/src/apub/activities.rs index c798dd795..4700bb089 100644 --- a/server/src/apub/activities.rs +++ b/server/src/apub/activities.rs @@ -7,7 +7,7 @@ use crate::{ ActorType, }, request::retry_custom, - DbPool, + LemmyContext, LemmyError, }; use activitystreams::base::AnyBase; @@ -23,16 +23,15 @@ pub async fn send_activity_to_community( community: &Community, to: Vec, activity: AnyBase, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result<(), LemmyError> { - insert_activity(creator.id, activity.clone(), true, pool).await?; + insert_activity(creator.id, activity.clone(), true, context.pool()).await?; // if this is a local community, we need to do an announce from the community instead if community.local { - do_announce(activity, &community, creator, client, pool).await?; + do_announce(activity, &community, creator, context).await?; } else { - send_activity(client, &activity, creator, to).await?; + send_activity(context.client(), &activity, creator, to).await?; } Ok(()) diff --git a/server/src/apub/comment.rs b/server/src/apub/comment.rs index f84bc609e..a9a97c083 100644 --- a/server/src/apub/comment.rs +++ b/server/src/apub/comment.rs @@ -18,8 +18,8 @@ use crate::{ ToApub, }, blocking, - routes::DbPoolParam, DbPool, + LemmyContext, LemmyError, }; use activitystreams::{ @@ -34,13 +34,12 @@ use activitystreams::{ Update, }, base::AnyBase, - context, link::Mention, object::{kind::NoteType, Note, Tombstone}, prelude::*, public, }; -use actix_web::{body::Body, client::Client, web::Path, HttpResponse}; +use actix_web::{body::Body, web, web::Path, HttpResponse}; use anyhow::Context; use itertools::Itertools; use lemmy_db::{ @@ -70,13 +69,15 @@ pub struct CommentQuery { /// Return the post json over HTTP. pub async fn get_apub_comment( info: Path, - db: DbPoolParam, + context: web::Data, ) -> Result, LemmyError> { let id = info.comment_id.parse::()?; - let comment = blocking(&db, move |conn| Comment::read(conn, id)).await??; + let comment = blocking(context.pool(), move |conn| Comment::read(conn, id)).await??; if !comment.deleted { - Ok(create_apub_response(&comment.to_apub(&db).await?)) + Ok(create_apub_response( + &comment.to_apub(context.pool()).await?, + )) } else { Ok(create_apub_tombstone_response(&comment.to_tombstone()?)) } @@ -110,7 +111,7 @@ impl ToApub for Comment { comment // Not needed when the Post is embedded in a collection (like for community outbox) - .set_context(context()) + .set_context(activitystreams::context()) .set_id(Url::parse(&self.ap_id)?) .set_published(convert_datetime(self.published)) .set_to(community.actor_id) @@ -137,8 +138,7 @@ impl FromApub for CommentForm { /// Parse an ActivityPub note received from another instance into a Lemmy comment async fn from_apub( note: &Note, - client: &Client, - pool: &DbPool, + context: &LemmyContext, expected_domain: Option, ) -> Result { let creator_actor_id = ¬e @@ -147,7 +147,7 @@ impl FromApub for CommentForm { .as_single_xsd_any_uri() .context(location_info!())?; - let creator = get_or_fetch_and_upsert_user(creator_actor_id, client, pool).await?; + let creator = get_or_fetch_and_upsert_user(creator_actor_id, context).await?; let mut in_reply_tos = note .in_reply_to() @@ -160,7 +160,7 @@ impl FromApub for CommentForm { let post_ap_id = in_reply_tos.next().context(location_info!())??; // This post, or the parent comment might not yet exist on this server yet, fetch them. - let post = get_or_fetch_and_insert_post(&post_ap_id, client, pool).await?; + let post = get_or_fetch_and_insert_post(&post_ap_id, context).await?; // The 2nd item, if it exists, is the parent comment apub_id // For deeply nested comments, FromApub automatically gets called recursively @@ -168,7 +168,7 @@ impl FromApub for CommentForm { Some(parent_comment_uri) => { let parent_comment_ap_id = &parent_comment_uri?; let parent_comment = - get_or_fetch_and_insert_comment(&parent_comment_ap_id, client, pool).await?; + get_or_fetch_and_insert_comment(&parent_comment_ap_id, context).await?; Some(parent_comment.id) } @@ -201,26 +201,23 @@ impl FromApub for CommentForm { #[async_trait::async_trait(?Send)] impl ApubObjectType for Comment { /// Send out information about a newly created comment, to the followers of the community. - async fn send_create( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let note = self.to_apub(pool).await?; + async fn send_create(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let note = self.to_apub(context.pool()).await?; let post_id = self.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let community_id = post.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; - let maa = - collect_non_local_mentions_and_addresses(&self.content, &community, client, pool).await?; + let maa = collect_non_local_mentions_and_addresses(&self.content, &community, context).await?; let mut create = Create::new(creator.actor_id.to_owned(), note.into_any_base()?); create - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(CreateType::Create)?) .set_to(public()) .set_many_ccs(maa.addressed_ccs.to_owned()) @@ -232,34 +229,30 @@ impl ApubObjectType for Comment { &community, maa.inboxes, create.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) } /// Send out information about an edited post, to the followers of the community. - async fn send_update( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let note = self.to_apub(pool).await?; + async fn send_update(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let note = self.to_apub(context.pool()).await?; let post_id = self.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let community_id = post.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; - let maa = - collect_non_local_mentions_and_addresses(&self.content, &community, client, pool).await?; + let maa = collect_non_local_mentions_and_addresses(&self.content, &community, context).await?; let mut update = Update::new(creator.actor_id.to_owned(), note.into_any_base()?); update - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(UpdateType::Update)?) .set_to(public()) .set_many_ccs(maa.addressed_ccs.to_owned()) @@ -271,30 +264,27 @@ impl ApubObjectType for Comment { &community, maa.inboxes, update.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) } - async fn send_delete( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let note = self.to_apub(pool).await?; + async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let note = self.to_apub(context.pool()).await?; let post_id = self.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let community_id = post.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?); delete - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(DeleteType::Delete)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -304,8 +294,7 @@ impl ApubObjectType for Comment { &community, vec![community.get_shared_inbox_url()?], delete.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) @@ -314,21 +303,23 @@ impl ApubObjectType for Comment { async fn send_undo_delete( &self, creator: &User_, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result<(), LemmyError> { - let note = self.to_apub(pool).await?; + let note = self.to_apub(context.pool()).await?; let post_id = self.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let community_id = post.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + 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(), note.into_any_base()?); delete - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(DeleteType::Delete)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -336,7 +327,7 @@ impl ApubObjectType for Comment { // Undo that fake activity let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?); undo - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(UndoType::Undo)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -346,30 +337,27 @@ impl ApubObjectType for Comment { &community, vec![community.get_shared_inbox_url()?], undo.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) } - async fn send_remove( - &self, - mod_: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let note = self.to_apub(pool).await?; + async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let note = self.to_apub(context.pool()).await?; let post_id = self.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let community_id = post.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; let mut remove = Remove::new(mod_.actor_id.to_owned(), note.into_any_base()?); remove - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(RemoveType::Remove)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -379,31 +367,28 @@ impl ApubObjectType for Comment { &community, vec![community.get_shared_inbox_url()?], remove.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) } - async fn send_undo_remove( - &self, - mod_: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let note = self.to_apub(pool).await?; + async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let note = self.to_apub(context.pool()).await?; let post_id = self.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let community_id = post.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + 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(), note.into_any_base()?); remove - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(RemoveType::Remove)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -411,7 +396,7 @@ impl ApubObjectType for Comment { // Undo that fake activity let mut undo = Undo::new(mod_.actor_id.to_owned(), remove.into_any_base()?); undo - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(UndoType::Undo)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -421,8 +406,7 @@ impl ApubObjectType for Comment { &community, vec![community.get_shared_inbox_url()?], undo.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) @@ -431,23 +415,21 @@ impl ApubObjectType for Comment { #[async_trait::async_trait(?Send)] impl ApubLikeableType for Comment { - async fn send_like( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let note = self.to_apub(pool).await?; + async fn send_like(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let note = self.to_apub(context.pool()).await?; let post_id = self.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let community_id = post.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; let mut like = Like::new(creator.actor_id.to_owned(), note.into_any_base()?); like - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(LikeType::Like)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -457,30 +439,27 @@ impl ApubLikeableType for Comment { &community, vec![community.get_shared_inbox_url()?], like.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) } - async fn send_dislike( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let note = self.to_apub(pool).await?; + async fn send_dislike(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let note = self.to_apub(context.pool()).await?; let post_id = self.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let community_id = post.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; let mut dislike = Dislike::new(creator.actor_id.to_owned(), note.into_any_base()?); dislike - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(DislikeType::Dislike)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -490,8 +469,7 @@ impl ApubLikeableType for Comment { &community, vec![community.get_shared_inbox_url()?], dislike.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) @@ -500,20 +478,22 @@ impl ApubLikeableType for Comment { async fn send_undo_like( &self, creator: &User_, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result<(), LemmyError> { - let note = self.to_apub(pool).await?; + let note = self.to_apub(context.pool()).await?; let post_id = self.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let community_id = post.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; let mut like = Like::new(creator.actor_id.to_owned(), note.into_any_base()?); like - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(DislikeType::Dislike)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -521,7 +501,7 @@ impl ApubLikeableType for Comment { // Undo that fake activity let mut undo = Undo::new(creator.actor_id.to_owned(), like.into_any_base()?); undo - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(UndoType::Undo)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -531,8 +511,7 @@ impl ApubLikeableType for Comment { &community, vec![community.get_shared_inbox_url()?], undo.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) @@ -561,8 +540,7 @@ impl MentionsAndAddresses { async fn collect_non_local_mentions_and_addresses( content: &str, community: &Community, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result { let mut addressed_ccs = vec![community.get_followers_url()?]; @@ -579,11 +557,11 @@ async fn collect_non_local_mentions_and_addresses( let mut mention_inboxes: Vec = Vec::new(); for mention in &mentions { // TODO should it be fetching it every time? - if let Ok(actor_id) = fetch_webfinger_url(mention, client).await { + if let Ok(actor_id) = fetch_webfinger_url(mention, context.client()).await { debug!("mention actor_id: {}", actor_id); addressed_ccs.push(actor_id.to_owned().to_string().parse()?); - let mention_user = get_or_fetch_and_upsert_user(&actor_id, client, pool).await?; + let mention_user = get_or_fetch_and_upsert_user(&actor_id, context).await?; let shared_inbox = mention_user.get_shared_inbox_url()?; mention_inboxes.push(shared_inbox); diff --git a/server/src/apub/community.rs b/server/src/apub/community.rs index adb4a3ca7..016f342dc 100644 --- a/server/src/apub/community.rs +++ b/server/src/apub/community.rs @@ -15,8 +15,8 @@ use crate::{ ToApub, }, blocking, - routes::DbPoolParam, DbPool, + LemmyContext, LemmyError, }; use activitystreams::{ @@ -32,13 +32,12 @@ use activitystreams::{ actor::{kind::GroupType, ApActor, Endpoints, Group}, base::{AnyBase, BaseExt}, collection::{OrderedCollection, UnorderedCollection}, - context, object::{Image, Tombstone}, prelude::*, public, }; use activitystreams_ext::Ext2; -use actix_web::{body::Body, client::Client, web, HttpResponse}; +use actix_web::{body::Body, web, HttpResponse}; use anyhow::Context; use itertools::Itertools; use lemmy_db::{ @@ -76,7 +75,7 @@ impl ToApub for Community { let mut group = Group::new(); group - .set_context(context()) + .set_context(activitystreams::context()) .set_id(Url::parse(&self.actor_id)?) .set_name(self.name.to_owned()) .set_published(convert_datetime(self.published)) @@ -139,124 +138,107 @@ impl ActorType for Community { async fn send_accept_follow( &self, follow: Follow, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result<(), LemmyError> { let actor_uri = follow .actor()? .as_single_xsd_any_uri() .context(location_info!())?; - let actor = get_or_fetch_and_upsert_actor(actor_uri, client, pool).await?; + let actor = get_or_fetch_and_upsert_actor(actor_uri, context).await?; let mut accept = Accept::new(self.actor_id.to_owned(), follow.into_any_base()?); let to = actor.get_inbox_url()?; accept - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(AcceptType::Accept)?) .set_to(to.clone()); - insert_activity(self.creator_id, accept.clone(), true, pool).await?; + insert_activity(self.creator_id, accept.clone(), true, context.pool()).await?; - send_activity(client, &accept.into_any_base()?, self, vec![to]).await?; + send_activity(context.client(), &accept.into_any_base()?, self, vec![to]).await?; Ok(()) } - async fn send_delete( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let group = self.to_apub(pool).await?; + async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let group = self.to_apub(context.pool()).await?; let mut delete = Delete::new(creator.actor_id.to_owned(), group.into_any_base()?); delete - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(DeleteType::Delete)?) .set_to(public()) .set_many_ccs(vec![self.get_followers_url()?]); - insert_activity(self.creator_id, delete.clone(), true, pool).await?; + insert_activity(self.creator_id, delete.clone(), true, context.pool()).await?; - let inboxes = self.get_follower_inboxes(pool).await?; + let inboxes = self.get_follower_inboxes(context.pool()).await?; // Note: For an accept, since it was automatic, no one pushed a button, // the community was the actor. // But for delete, the creator is the actor, and does the signing - send_activity(client, &delete.into_any_base()?, creator, inboxes).await?; + send_activity(context.client(), &delete.into_any_base()?, creator, inboxes).await?; Ok(()) } async fn send_undo_delete( &self, creator: &User_, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result<(), LemmyError> { - let group = self.to_apub(pool).await?; + let group = self.to_apub(context.pool()).await?; let mut delete = Delete::new(creator.actor_id.to_owned(), group.into_any_base()?); delete - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(DeleteType::Delete)?) .set_to(public()) .set_many_ccs(vec![self.get_followers_url()?]); let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?); undo - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(UndoType::Undo)?) .set_to(public()) .set_many_ccs(vec![self.get_followers_url()?]); - insert_activity(self.creator_id, undo.clone(), true, pool).await?; + insert_activity(self.creator_id, undo.clone(), true, context.pool()).await?; - let inboxes = self.get_follower_inboxes(pool).await?; + let inboxes = self.get_follower_inboxes(context.pool()).await?; // Note: For an accept, since it was automatic, no one pushed a button, // the community was the actor. // But for delete, the creator is the actor, and does the signing - send_activity(client, &undo.into_any_base()?, creator, inboxes).await?; + send_activity(context.client(), &undo.into_any_base()?, creator, inboxes).await?; Ok(()) } - async fn send_remove( - &self, - mod_: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let group = self.to_apub(pool).await?; + async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let group = self.to_apub(context.pool()).await?; let mut remove = Remove::new(mod_.actor_id.to_owned(), group.into_any_base()?); remove - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(RemoveType::Remove)?) .set_to(public()) .set_many_ccs(vec![self.get_followers_url()?]); - insert_activity(mod_.id, remove.clone(), true, pool).await?; + insert_activity(mod_.id, remove.clone(), true, context.pool()).await?; - let inboxes = self.get_follower_inboxes(pool).await?; + let inboxes = self.get_follower_inboxes(context.pool()).await?; // Note: For an accept, since it was automatic, no one pushed a button, // the community was the actor. // But for delete, the creator is the actor, and does the signing - send_activity(client, &remove.into_any_base()?, mod_, inboxes).await?; + send_activity(context.client(), &remove.into_any_base()?, mod_, inboxes).await?; Ok(()) } - async fn send_undo_remove( - &self, - mod_: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let group = self.to_apub(pool).await?; + async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let group = self.to_apub(context.pool()).await?; let mut remove = Remove::new(mod_.actor_id.to_owned(), group.into_any_base()?); remove - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(RemoveType::Remove)?) .set_to(public()) .set_many_ccs(vec![self.get_followers_url()?]); @@ -264,19 +246,19 @@ impl ActorType for Community { // Undo that fake activity let mut undo = Undo::new(mod_.actor_id.to_owned(), remove.into_any_base()?); undo - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(LikeType::Like)?) .set_to(public()) .set_many_ccs(vec![self.get_followers_url()?]); - insert_activity(mod_.id, undo.clone(), true, pool).await?; + insert_activity(mod_.id, undo.clone(), true, context.pool()).await?; - let inboxes = self.get_follower_inboxes(pool).await?; + let inboxes = self.get_follower_inboxes(context.pool()).await?; // Note: For an accept, since it was automatic, no one pushed a button, // the community was the actor. // But for remove , the creator is the actor, and does the signing - send_activity(client, &undo.into_any_base()?, mod_, inboxes).await?; + send_activity(context.client(), &undo.into_any_base()?, mod_, inboxes).await?; Ok(()) } @@ -318,8 +300,7 @@ impl ActorType for Community { async fn send_follow( &self, _follow_actor_id: &Url, - _client: &Client, - _pool: &DbPool, + _context: &LemmyContext, ) -> Result<(), LemmyError> { unimplemented!() } @@ -327,8 +308,7 @@ impl ActorType for Community { async fn send_unfollow( &self, _follow_actor_id: &Url, - _client: &Client, - _pool: &DbPool, + _context: &LemmyContext, ) -> Result<(), LemmyError> { unimplemented!() } @@ -345,8 +325,7 @@ impl FromApub for CommunityForm { /// Parse an ActivityPub group received from another instance into a Lemmy community. async fn from_apub( group: &GroupExt, - client: &Client, - pool: &DbPool, + context: &LemmyContext, expected_domain: Option, ) -> Result { let creator_and_moderator_uris = group.inner.attributed_to().context(location_info!())?; @@ -359,7 +338,7 @@ impl FromApub for CommunityForm { .as_xsd_any_uri() .context(location_info!())?; - let creator = get_or_fetch_and_upsert_user(creator_uri, client, pool).await?; + let creator = get_or_fetch_and_upsert_user(creator_uri, context).await?; let name = group .inner .name() @@ -437,15 +416,15 @@ impl FromApub for CommunityForm { /// Return the community json over HTTP. pub async fn get_apub_community_http( info: web::Path, - db: DbPoolParam, + context: web::Data, ) -> Result, LemmyError> { - let community = blocking(&db, move |conn| { + let community = blocking(context.pool(), move |conn| { Community::read_from_name(conn, &info.community_name) }) .await??; if !community.deleted { - let apub = community.to_apub(&db).await?; + let apub = community.to_apub(context.pool()).await?; Ok(create_apub_response(&apub)) } else { @@ -456,22 +435,22 @@ pub async fn get_apub_community_http( /// Returns an empty followers collection, only populating the size (for privacy). pub async fn get_apub_community_followers( info: web::Path, - db: DbPoolParam, + context: web::Data, ) -> Result, LemmyError> { - let community = blocking(&db, move |conn| { + let community = blocking(context.pool(), move |conn| { Community::read_from_name(&conn, &info.community_name) }) .await??; let community_id = community.id; - let community_followers = blocking(&db, move |conn| { + let community_followers = blocking(context.pool(), move |conn| { CommunityFollowerView::for_community(&conn, community_id) }) .await??; let mut collection = UnorderedCollection::new(); collection - .set_context(context()) + .set_context(activitystreams::context()) .set_id(community.get_followers_url()?) .set_total_items(community_followers.len() as u64); Ok(create_apub_response(&collection)) @@ -479,29 +458,29 @@ pub async fn get_apub_community_followers( pub async fn get_apub_community_outbox( info: web::Path, - db: DbPoolParam, + context: web::Data, ) -> Result, LemmyError> { - let community = blocking(&db, move |conn| { + let community = blocking(context.pool(), move |conn| { Community::read_from_name(&conn, &info.community_name) }) .await??; let community_id = community.id; - let posts = blocking(&db, move |conn| { + let posts = blocking(context.pool(), move |conn| { Post::list_for_community(conn, community_id) }) .await??; let mut pages: Vec = vec![]; for p in posts { - pages.push(p.to_apub(&db).await?.into_any_base()?); + pages.push(p.to_apub(context.pool()).await?.into_any_base()?); } let len = pages.len(); let mut collection = OrderedCollection::new(); collection .set_many_items(pages) - .set_context(context()) + .set_context(activitystreams::context()) .set_id(community.get_outbox_url()?) .set_total_items(len as u64); Ok(create_apub_response(&collection)) @@ -511,19 +490,18 @@ pub async fn do_announce( activity: AnyBase, community: &Community, sender: &User_, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result<(), LemmyError> { let mut announce = Announce::new(community.actor_id.to_owned(), activity); announce - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(AnnounceType::Announce)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); - insert_activity(community.creator_id, announce.clone(), true, pool).await?; + insert_activity(community.creator_id, announce.clone(), true, context.pool()).await?; - let mut to: Vec = community.get_follower_inboxes(pool).await?; + let mut to: Vec = community.get_follower_inboxes(context.pool()).await?; // dont send to the local instance, nor to the instance where the activity originally came from, // because that would result in a database error (same data inserted twice) @@ -533,7 +511,7 @@ pub async fn do_announce( let community_shared_inbox = community.get_shared_inbox_url()?; to.retain(|x| x != &community_shared_inbox); - send_activity(client, &announce.into_any_base()?, community, to).await?; + send_activity(context.client(), &announce.into_any_base()?, community, to).await?; Ok(()) } diff --git a/server/src/apub/fetcher.rs b/server/src/apub/fetcher.rs index d8eaf70a7..0c42aa14e 100644 --- a/server/src/apub/fetcher.rs +++ b/server/src/apub/fetcher.rs @@ -11,7 +11,7 @@ use crate::{ }, blocking, request::{retry, RecvError}, - DbPool, + LemmyContext, LemmyError, }; use activitystreams::{base::BaseExt, collection::OrderedCollection, object::Note, prelude::*}; @@ -92,8 +92,7 @@ pub enum SearchAcceptedObjects { /// http://lemmy_alpha:8540/comment/2 pub async fn search_by_apub_id( query: &str, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result { // Parse the shorthand query url let query_url = if query.contains('@') { @@ -130,62 +129,74 @@ pub async fn search_by_apub_id( }; let domain = query_url.domain().context("url has no domain")?; - let response = match fetch_remote_object::(client, &query_url).await? { - SearchAcceptedObjects::Person(p) => { - let user_uri = p.inner.id(domain)?.context("person has no id")?; + let response = + match fetch_remote_object::(context.client(), &query_url).await? { + SearchAcceptedObjects::Person(p) => { + let user_uri = p.inner.id(domain)?.context("person has no id")?; - let user = get_or_fetch_and_upsert_user(&user_uri, client, pool).await?; + let user = get_or_fetch_and_upsert_user(&user_uri, context).await?; - response.users = - vec![blocking(pool, move |conn| UserView::get_user_secure(conn, user.id)).await??]; + response.users = vec![ + blocking(context.pool(), move |conn| { + UserView::get_user_secure(conn, user.id) + }) + .await??, + ]; - response - } - SearchAcceptedObjects::Group(g) => { - let community_uri = g.inner.id(domain)?.context("group has no id")?; + response + } + SearchAcceptedObjects::Group(g) => { + let community_uri = g.inner.id(domain)?.context("group has no id")?; - let community = get_or_fetch_and_upsert_community(community_uri, client, pool).await?; + let community = get_or_fetch_and_upsert_community(community_uri, context).await?; - response.communities = vec![ - blocking(pool, move |conn| { - CommunityView::read(conn, community.id, None) + response.communities = vec![ + blocking(context.pool(), move |conn| { + CommunityView::read(conn, community.id, None) + }) + .await??, + ]; + + response + } + SearchAcceptedObjects::Page(p) => { + let post_form = PostForm::from_apub(&p, context, Some(query_url)).await?; + + let p = blocking(context.pool(), move |conn| Post::upsert(conn, &post_form)).await??; + response.posts = + vec![blocking(context.pool(), move |conn| PostView::read(conn, p.id, None)).await??]; + + response + } + SearchAcceptedObjects::Comment(c) => { + let comment_form = CommentForm::from_apub(&c, context, Some(query_url)).await?; + + let c = blocking(context.pool(), move |conn| { + Comment::upsert(conn, &comment_form) }) - .await??, - ]; + .await??; + response.comments = vec![ + blocking(context.pool(), move |conn| { + CommentView::read(conn, c.id, None) + }) + .await??, + ]; - response - } - SearchAcceptedObjects::Page(p) => { - let post_form = PostForm::from_apub(&p, client, pool, Some(query_url)).await?; - - let p = blocking(pool, move |conn| Post::upsert(conn, &post_form)).await??; - response.posts = vec![blocking(pool, move |conn| PostView::read(conn, p.id, None)).await??]; - - response - } - SearchAcceptedObjects::Comment(c) => { - let comment_form = CommentForm::from_apub(&c, client, pool, Some(query_url)).await?; - - let c = blocking(pool, move |conn| Comment::upsert(conn, &comment_form)).await??; - response.comments = - vec![blocking(pool, move |conn| CommentView::read(conn, c.id, None)).await??]; - - response - } - }; + response + } + }; Ok(response) } pub async fn get_or_fetch_and_upsert_actor( apub_id: &Url, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result, LemmyError> { - let user = get_or_fetch_and_upsert_user(apub_id, client, pool).await; + let user = get_or_fetch_and_upsert_user(apub_id, context).await; let actor: Box = match user { Ok(u) => Box::new(u), - Err(_) => Box::new(get_or_fetch_and_upsert_community(apub_id, client, pool).await?), + Err(_) => Box::new(get_or_fetch_and_upsert_community(apub_id, context).await?), }; Ok(actor) } @@ -193,11 +204,10 @@ pub async fn get_or_fetch_and_upsert_actor( /// Check if a remote user exists, create if not found, if its too old update it.Fetch a user, insert/update it in the database and return the user. pub async fn get_or_fetch_and_upsert_user( apub_id: &Url, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result { let apub_id_owned = apub_id.to_owned(); - let user = blocking(pool, move |conn| { + let user = blocking(context.pool(), move |conn| { User_::read_from_actor_id(conn, apub_id_owned.as_ref()) }) .await?; @@ -206,21 +216,21 @@ pub async fn get_or_fetch_and_upsert_user( // If its older than a day, re-fetch it Ok(u) if !u.local && should_refetch_actor(u.last_refreshed_at) => { debug!("Fetching and updating from remote user: {}", apub_id); - let person = fetch_remote_object::(client, apub_id).await?; + let person = fetch_remote_object::(context.client(), apub_id).await?; - let mut uf = UserForm::from_apub(&person, client, pool, Some(apub_id.to_owned())).await?; + let mut uf = UserForm::from_apub(&person, context, Some(apub_id.to_owned())).await?; uf.last_refreshed_at = Some(naive_now()); - let user = blocking(pool, move |conn| User_::update(conn, u.id, &uf)).await??; + let user = blocking(context.pool(), move |conn| User_::update(conn, u.id, &uf)).await??; Ok(user) } Ok(u) => Ok(u), Err(NotFound {}) => { debug!("Fetching and creating remote user: {}", apub_id); - let person = fetch_remote_object::(client, apub_id).await?; + let person = fetch_remote_object::(context.client(), apub_id).await?; - let uf = UserForm::from_apub(&person, client, pool, Some(apub_id.to_owned())).await?; - let user = blocking(pool, move |conn| User_::create(conn, &uf)).await??; + let uf = UserForm::from_apub(&person, context, Some(apub_id.to_owned())).await?; + let user = blocking(context.pool(), move |conn| User_::create(conn, &uf)).await??; Ok(user) } @@ -246,11 +256,10 @@ fn should_refetch_actor(last_refreshed: NaiveDateTime) -> bool { /// Check if a remote community exists, create if not found, if its too old update it.Fetch a community, insert/update it in the database and return the community. pub async fn get_or_fetch_and_upsert_community( apub_id: &Url, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result { let apub_id_owned = apub_id.to_owned(); - let community = blocking(pool, move |conn| { + let community = blocking(context.pool(), move |conn| { Community::read_from_actor_id(conn, apub_id_owned.as_str()) }) .await?; @@ -258,12 +267,12 @@ pub async fn get_or_fetch_and_upsert_community( match community { Ok(c) if !c.local && should_refetch_actor(c.last_refreshed_at) => { debug!("Fetching and updating from remote community: {}", apub_id); - fetch_remote_community(apub_id, client, pool, Some(c.id)).await + fetch_remote_community(apub_id, context, Some(c.id)).await } Ok(c) => Ok(c), Err(NotFound {}) => { debug!("Fetching and creating remote community: {}", apub_id); - fetch_remote_community(apub_id, client, pool, None).await + fetch_remote_community(apub_id, context, None).await } Err(e) => Err(e.into()), } @@ -271,14 +280,13 @@ pub async fn get_or_fetch_and_upsert_community( async fn fetch_remote_community( apub_id: &Url, - client: &Client, - pool: &DbPool, + context: &LemmyContext, community_id: Option, ) -> Result { - let group = fetch_remote_object::(client, apub_id).await?; + let group = fetch_remote_object::(context.client(), apub_id).await?; - let cf = CommunityForm::from_apub(&group, client, pool, Some(apub_id.to_owned())).await?; - let community = blocking(pool, move |conn| { + let cf = CommunityForm::from_apub(&group, context, Some(apub_id.to_owned())).await?; + let community = blocking(context.pool(), move |conn| { if let Some(cid) = community_id { Community::update(conn, cid, &cf) } else { @@ -299,7 +307,7 @@ async fn fetch_remote_community( let mut creator_and_moderators = Vec::new(); for uri in creator_and_moderator_uris { - let c_or_m = get_or_fetch_and_upsert_user(uri, client, pool).await?; + let c_or_m = get_or_fetch_and_upsert_user(uri, context).await?; creator_and_moderators.push(c_or_m); } @@ -307,7 +315,7 @@ async fn fetch_remote_community( // TODO: need to make this work to update mods of existing communities if community_id.is_none() { let community_id = community.id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { for mod_ in creator_and_moderators { let community_moderator_form = CommunityModeratorForm { community_id, @@ -323,7 +331,8 @@ async fn fetch_remote_community( // fetch outbox (maybe make this conditional) let outbox = - fetch_remote_object::(client, &community.get_outbox_url()?).await?; + fetch_remote_object::(context.client(), &community.get_outbox_url()?) + .await?; let outbox_items = outbox.items().context(location_info!())?.clone(); let mut outbox_items = outbox_items.many().context(location_info!())?; if outbox_items.len() > 20 { @@ -331,13 +340,16 @@ async fn fetch_remote_community( } for o in outbox_items { let page = PageExt::from_any_base(o)?.context(location_info!())?; - let post = PostForm::from_apub(&page, client, pool, None).await?; + let post = PostForm::from_apub(&page, context, None).await?; let post_ap_id = post.ap_id.clone(); // Check whether the post already exists in the local db - let existing = blocking(pool, move |conn| Post::read_from_apub_id(conn, &post_ap_id)).await?; + let existing = blocking(context.pool(), move |conn| { + Post::read_from_apub_id(conn, &post_ap_id) + }) + .await?; match existing { - Ok(e) => blocking(pool, move |conn| Post::update(conn, e.id, &post)).await??, - Err(_) => blocking(pool, move |conn| Post::create(conn, &post)).await??, + Ok(e) => blocking(context.pool(), move |conn| Post::update(conn, e.id, &post)).await??, + Err(_) => blocking(context.pool(), move |conn| Post::create(conn, &post)).await??, }; // TODO: we need to send a websocket update here } @@ -347,11 +359,10 @@ async fn fetch_remote_community( pub async fn get_or_fetch_and_insert_post( post_ap_id: &Url, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result { let post_ap_id_owned = post_ap_id.to_owned(); - let post = blocking(pool, move |conn| { + let post = blocking(context.pool(), move |conn| { Post::read_from_apub_id(conn, post_ap_id_owned.as_str()) }) .await?; @@ -360,10 +371,10 @@ pub async fn get_or_fetch_and_insert_post( Ok(p) => Ok(p), Err(NotFound {}) => { debug!("Fetching and creating remote post: {}", post_ap_id); - let post = fetch_remote_object::(client, post_ap_id).await?; - let post_form = PostForm::from_apub(&post, client, pool, Some(post_ap_id.to_owned())).await?; + let post = fetch_remote_object::(context.client(), post_ap_id).await?; + let post_form = PostForm::from_apub(&post, context, Some(post_ap_id.to_owned())).await?; - let post = blocking(pool, move |conn| Post::create(conn, &post_form)).await??; + let post = blocking(context.pool(), move |conn| Post::create(conn, &post_form)).await??; Ok(post) } @@ -373,11 +384,10 @@ pub async fn get_or_fetch_and_insert_post( pub async fn get_or_fetch_and_insert_comment( comment_ap_id: &Url, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result { let comment_ap_id_owned = comment_ap_id.to_owned(); - let comment = blocking(pool, move |conn| { + let comment = blocking(context.pool(), move |conn| { Comment::read_from_apub_id(conn, comment_ap_id_owned.as_str()) }) .await?; @@ -389,11 +399,14 @@ pub async fn get_or_fetch_and_insert_comment( "Fetching and creating remote comment and its parents: {}", comment_ap_id ); - let comment = fetch_remote_object::(client, comment_ap_id).await?; + let comment = fetch_remote_object::(context.client(), comment_ap_id).await?; let comment_form = - CommentForm::from_apub(&comment, client, pool, Some(comment_ap_id.to_owned())).await?; + CommentForm::from_apub(&comment, context, Some(comment_ap_id.to_owned())).await?; - let comment = blocking(pool, move |conn| Comment::create(conn, &comment_form)).await??; + let comment = blocking(context.pool(), move |conn| { + Comment::create(conn, &comment_form) + }) + .await??; Ok(comment) } diff --git a/server/src/apub/inbox/activities/announce.rs b/server/src/apub/inbox/activities/announce.rs index b7e9a71fc..e0fb8065d 100644 --- a/server/src/apub/inbox/activities/announce.rs +++ b/server/src/apub/inbox/activities/announce.rs @@ -11,8 +11,7 @@ use crate::{ }, shared_inbox::{get_community_id_from_activity, receive_unhandled_activity}, }, - routes::ChatServerParam, - DbPool, + LemmyContext, LemmyError, }; use activitystreams::{ @@ -20,15 +19,13 @@ use activitystreams::{ base::{AnyBase, BaseExt}, prelude::ExtendsExt, }; -use actix_web::{client::Client, HttpResponse}; +use actix_web::HttpResponse; use anyhow::Context; use lemmy_utils::location_info; pub async fn receive_announce( activity: AnyBase, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let announce = Announce::from_any_base(activity)?.context(location_info!())?; @@ -40,13 +37,13 @@ pub async fn receive_announce( let object = announce.object(); let object2 = object.clone().one().context(location_info!())?; match kind { - Some("Create") => receive_create(object2, client, pool, chat_server).await, - Some("Update") => receive_update(object2, client, pool, chat_server).await, - Some("Like") => receive_like(object2, client, pool, chat_server).await, - Some("Dislike") => receive_dislike(object2, client, pool, chat_server).await, - Some("Delete") => receive_delete(object2, client, pool, chat_server).await, - Some("Remove") => receive_remove(object2, client, pool, chat_server).await, - Some("Undo") => receive_undo(object2, client, pool, chat_server).await, + Some("Create") => receive_create(object2, context).await, + Some("Update") => receive_update(object2, context).await, + Some("Like") => receive_like(object2, context).await, + Some("Dislike") => receive_dislike(object2, context).await, + Some("Delete") => receive_delete(object2, context).await, + Some("Remove") => receive_remove(object2, context).await, + Some("Undo") => receive_undo(object2, context).await, _ => receive_unhandled_activity(announce), } } diff --git a/server/src/apub/inbox/activities/create.rs b/server/src/apub/inbox/activities/create.rs index 6967b261c..696aca9ee 100644 --- a/server/src/apub/inbox/activities/create.rs +++ b/server/src/apub/inbox/activities/create.rs @@ -14,16 +14,15 @@ use crate::{ PageExt, }, blocking, - routes::ChatServerParam, websocket::{ server::{SendComment, SendPost}, UserOperation, }, - DbPool, + LemmyContext, LemmyError, }; use activitystreams::{activity::Create, base::AnyBase, object::Note, prelude::*}; -use actix_web::{client::Client, HttpResponse}; +use actix_web::HttpResponse; use anyhow::Context; use lemmy_db::{ comment::{Comment, CommentForm}, @@ -35,85 +34,87 @@ use lemmy_utils::{location_info, scrape_text_for_mentions}; pub async fn receive_create( activity: AnyBase, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let create = Create::from_any_base(activity)?.context(location_info!())?; // ensure that create and actor come from the same instance - let user = get_user_from_activity(&create, client, pool).await?; + let user = get_user_from_activity(&create, context).await?; create.id(user.actor_id()?.domain().context(location_info!())?)?; match create.object().as_single_kind_str() { - Some("Page") => receive_create_post(create, client, pool, chat_server).await, - Some("Note") => receive_create_comment(create, client, pool, chat_server).await, + Some("Page") => receive_create_post(create, context).await, + Some("Note") => receive_create_comment(create, context).await, _ => receive_unhandled_activity(create), } } async fn receive_create_post( create: Create, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let user = get_user_from_activity(&create, client, pool).await?; + let user = get_user_from_activity(&create, context).await?; let page = PageExt::from_any_base(create.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let post = PostForm::from_apub(&page, client, pool, Some(user.actor_id()?)).await?; + let post = PostForm::from_apub(&page, context, Some(user.actor_id()?)).await?; // Using an upsert, since likes (which fetch the post), sometimes come in before the create // resulting in double posts. - let inserted_post = blocking(pool, move |conn| Post::upsert(conn, &post)).await??; + let inserted_post = blocking(context.pool(), move |conn| Post::upsert(conn, &post)).await??; // Refetch the view let inserted_post_id = inserted_post.id; - let post_view = blocking(pool, move |conn| { + let post_view = blocking(context.pool(), move |conn| { PostView::read(conn, inserted_post_id, None) }) .await??; let res = PostResponse { post: post_view }; - chat_server.do_send(SendPost { + context.chat_server().do_send(SendPost { op: UserOperation::CreatePost, post: res, my_id: None, }); - announce_if_community_is_local(create, &user, client, pool).await?; + announce_if_community_is_local(create, &user, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_create_comment( create: Create, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let user = get_user_from_activity(&create, client, pool).await?; + let user = get_user_from_activity(&create, context).await?; let note = Note::from_any_base(create.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let comment = CommentForm::from_apub(¬e, client, pool, Some(user.actor_id()?)).await?; + let comment = CommentForm::from_apub(¬e, context, Some(user.actor_id()?)).await?; - let inserted_comment = blocking(pool, move |conn| Comment::upsert(conn, &comment)).await??; + let inserted_comment = + blocking(context.pool(), move |conn| Comment::upsert(conn, &comment)).await??; let post_id = inserted_comment.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; // Note: // Although mentions could be gotten from the post tags (they are included there), or the ccs, // Its much easier to scrape them from the comment body, since the API has to do that // anyway. let mentions = scrape_text_for_mentions(&inserted_comment.content); - let recipient_ids = - send_local_notifs(mentions, inserted_comment.clone(), &user, post, pool, true).await?; + let recipient_ids = send_local_notifs( + mentions, + inserted_comment.clone(), + &user, + post, + context.pool(), + true, + ) + .await?; // Refetch the view - let comment_view = blocking(pool, move |conn| { + let comment_view = blocking(context.pool(), move |conn| { CommentView::read(conn, inserted_comment.id, None) }) .await??; @@ -124,12 +125,12 @@ async fn receive_create_comment( form_id: None, }; - chat_server.do_send(SendComment { + context.chat_server().do_send(SendComment { op: UserOperation::CreateComment, comment: res, my_id: None, }); - announce_if_community_is_local(create, &user, client, pool).await?; + announce_if_community_is_local(create, &user, context).await?; Ok(HttpResponse::Ok().finish()) } diff --git a/server/src/apub/inbox/activities/delete.rs b/server/src/apub/inbox/activities/delete.rs index 7a56eb45b..c9ab042ae 100644 --- a/server/src/apub/inbox/activities/delete.rs +++ b/server/src/apub/inbox/activities/delete.rs @@ -13,16 +13,15 @@ use crate::{ PageExt, }, blocking, - routes::ChatServerParam, websocket::{ server::{SendComment, SendCommunityRoomMessage, SendPost}, UserOperation, }, - DbPool, + LemmyContext, LemmyError, }; use activitystreams::{activity::Delete, base::AnyBase, object::Note, prelude::*}; -use actix_web::{client::Client, HttpResponse}; +use actix_web::HttpResponse; use anyhow::Context; use lemmy_db::{ comment::{Comment, CommentForm}, @@ -38,34 +37,30 @@ use lemmy_utils::location_info; pub async fn receive_delete( activity: AnyBase, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let delete = Delete::from_any_base(activity)?.context(location_info!())?; match delete.object().as_single_kind_str() { - Some("Page") => receive_delete_post(delete, client, pool, chat_server).await, - Some("Note") => receive_delete_comment(delete, client, pool, chat_server).await, - Some("Group") => receive_delete_community(delete, client, pool, chat_server).await, + Some("Page") => receive_delete_post(delete, context).await, + Some("Note") => receive_delete_comment(delete, context).await, + Some("Group") => receive_delete_community(delete, context).await, _ => receive_unhandled_activity(delete), } } async fn receive_delete_post( delete: Delete, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let user = get_user_from_activity(&delete, client, pool).await?; + let user = get_user_from_activity(&delete, context).await?; let page = PageExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let post_ap_id = PostForm::from_apub(&page, client, pool, Some(user.actor_id()?)) + let post_ap_id = PostForm::from_apub(&page, context, Some(user.actor_id()?)) .await? .get_ap_id()?; - let post = get_or_fetch_and_insert_post(&post_ap_id, client, pool).await?; + let post = get_or_fetch_and_insert_post(&post_ap_id, context).await?; let post_form = PostForm { name: post.name.to_owned(), @@ -88,39 +83,43 @@ async fn receive_delete_post( published: None, }; let post_id = post.id; - blocking(pool, move |conn| Post::update(conn, post_id, &post_form)).await??; + blocking(context.pool(), move |conn| { + Post::update(conn, post_id, &post_form) + }) + .await??; // Refetch the view let post_id = post.id; - let post_view = blocking(pool, move |conn| PostView::read(conn, post_id, None)).await??; + let post_view = blocking(context.pool(), move |conn| { + PostView::read(conn, post_id, None) + }) + .await??; let res = PostResponse { post: post_view }; - chat_server.do_send(SendPost { + context.chat_server().do_send(SendPost { op: UserOperation::EditPost, post: res, my_id: None, }); - announce_if_community_is_local(delete, &user, client, pool).await?; + announce_if_community_is_local(delete, &user, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_delete_comment( delete: Delete, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let user = get_user_from_activity(&delete, client, pool).await?; + let user = get_user_from_activity(&delete, context).await?; let note = Note::from_any_base(delete.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let comment_ap_id = CommentForm::from_apub(¬e, client, pool, Some(user.actor_id()?)) + let comment_ap_id = CommentForm::from_apub(¬e, context, Some(user.actor_id()?)) .await? .get_ap_id()?; - let comment = get_or_fetch_and_insert_comment(&comment_ap_id, client, pool).await?; + let comment = get_or_fetch_and_insert_comment(&comment_ap_id, context).await?; let comment_form = CommentForm { content: comment.content.to_owned(), @@ -136,15 +135,17 @@ async fn receive_delete_comment( local: comment.local, }; let comment_id = comment.id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { Comment::update(conn, comment_id, &comment_form) }) .await??; // Refetch the view let comment_id = comment.id; - let comment_view = - blocking(pool, move |conn| CommentView::read(conn, comment_id, None)).await??; + let comment_view = blocking(context.pool(), move |conn| { + CommentView::read(conn, comment_id, None) + }) + .await??; // TODO get those recipient actor ids from somewhere let recipient_ids = vec![]; @@ -154,31 +155,29 @@ async fn receive_delete_comment( form_id: None, }; - chat_server.do_send(SendComment { + context.chat_server().do_send(SendComment { op: UserOperation::EditComment, comment: res, my_id: None, }); - announce_if_community_is_local(delete, &user, client, pool).await?; + announce_if_community_is_local(delete, &user, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_delete_community( delete: Delete, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let group = GroupExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let user = get_user_from_activity(&delete, client, pool).await?; + let user = get_user_from_activity(&delete, context).await?; - let community_actor_id = CommunityForm::from_apub(&group, client, pool, Some(user.actor_id()?)) + let community_actor_id = CommunityForm::from_apub(&group, context, Some(user.actor_id()?)) .await? .actor_id; - let community = blocking(pool, move |conn| { + let community = blocking(context.pool(), move |conn| { Community::read_from_actor_id(conn, &community_actor_id) }) .await??; @@ -204,14 +203,14 @@ async fn receive_delete_community( }; let community_id = community.id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { Community::update(conn, community_id, &community_form) }) .await??; let community_id = community.id; let res = CommunityResponse { - community: blocking(pool, move |conn| { + community: blocking(context.pool(), move |conn| { CommunityView::read(conn, community_id, None) }) .await??, @@ -219,13 +218,13 @@ async fn receive_delete_community( let community_id = res.community.id; - chat_server.do_send(SendCommunityRoomMessage { + context.chat_server().do_send(SendCommunityRoomMessage { op: UserOperation::EditCommunity, response: res, community_id, my_id: None, }); - announce_if_community_is_local(delete, &user, client, pool).await?; + announce_if_community_is_local(delete, &user, context).await?; Ok(HttpResponse::Ok().finish()) } diff --git a/server/src/apub/inbox/activities/dislike.rs b/server/src/apub/inbox/activities/dislike.rs index 07f5ac30b..e1d3006a3 100644 --- a/server/src/apub/inbox/activities/dislike.rs +++ b/server/src/apub/inbox/activities/dislike.rs @@ -11,16 +11,15 @@ use crate::{ PageExt, }, blocking, - routes::ChatServerParam, websocket::{ server::{SendComment, SendPost}, UserOperation, }, - DbPool, + LemmyContext, LemmyError, }; use activitystreams::{activity::Dislike, base::AnyBase, object::Note, prelude::*}; -use actix_web::{client::Client, HttpResponse}; +use actix_web::HttpResponse; use anyhow::Context; use lemmy_db::{ comment::{CommentForm, CommentLike, CommentLikeForm}, @@ -33,25 +32,21 @@ use lemmy_utils::location_info; pub async fn receive_dislike( activity: AnyBase, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let dislike = Dislike::from_any_base(activity)?.context(location_info!())?; match dislike.object().as_single_kind_str() { - Some("Page") => receive_dislike_post(dislike, client, pool, chat_server).await, - Some("Note") => receive_dislike_comment(dislike, client, pool, chat_server).await, + Some("Page") => receive_dislike_post(dislike, context).await, + Some("Note") => receive_dislike_comment(dislike, context).await, _ => receive_unhandled_activity(dislike), } } async fn receive_dislike_post( dislike: Dislike, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let user = get_user_from_activity(&dislike, client, pool).await?; + let user = get_user_from_activity(&dislike, context).await?; let page = PageExt::from_any_base( dislike .object() @@ -61,9 +56,9 @@ async fn receive_dislike_post( )? .context(location_info!())?; - let post = PostForm::from_apub(&page, client, pool, None).await?; + let post = PostForm::from_apub(&page, context, None).await?; - let post_id = get_or_fetch_and_insert_post(&post.get_ap_id()?, client, pool) + let post_id = get_or_fetch_and_insert_post(&post.get_ap_id()?, context) .await? .id; @@ -73,32 +68,33 @@ async fn receive_dislike_post( score: -1, }; let user_id = user.id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { PostLike::remove(conn, user_id, post_id)?; PostLike::like(conn, &like_form) }) .await??; // Refetch the view - let post_view = blocking(pool, move |conn| PostView::read(conn, post_id, None)).await??; + let post_view = blocking(context.pool(), move |conn| { + PostView::read(conn, post_id, None) + }) + .await??; let res = PostResponse { post: post_view }; - chat_server.do_send(SendPost { + context.chat_server().do_send(SendPost { op: UserOperation::CreatePostLike, post: res, my_id: None, }); - announce_if_community_is_local(dislike, &user, client, pool).await?; + announce_if_community_is_local(dislike, &user, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_dislike_comment( dislike: Dislike, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let note = Note::from_any_base( dislike @@ -108,11 +104,11 @@ async fn receive_dislike_comment( .context(location_info!())?, )? .context(location_info!())?; - let user = get_user_from_activity(&dislike, client, pool).await?; + let user = get_user_from_activity(&dislike, context).await?; - let comment = CommentForm::from_apub(¬e, client, pool, None).await?; + let comment = CommentForm::from_apub(¬e, context, None).await?; - let comment_id = get_or_fetch_and_insert_comment(&comment.get_ap_id()?, client, pool) + let comment_id = get_or_fetch_and_insert_comment(&comment.get_ap_id()?, context) .await? .id; @@ -123,15 +119,17 @@ async fn receive_dislike_comment( score: -1, }; let user_id = user.id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { CommentLike::remove(conn, user_id, comment_id)?; CommentLike::like(conn, &like_form) }) .await??; // Refetch the view - let comment_view = - blocking(pool, move |conn| CommentView::read(conn, comment_id, None)).await??; + let comment_view = blocking(context.pool(), move |conn| { + CommentView::read(conn, comment_id, None) + }) + .await??; // TODO get those recipient actor ids from somewhere let recipient_ids = vec![]; @@ -141,12 +139,12 @@ async fn receive_dislike_comment( form_id: None, }; - chat_server.do_send(SendComment { + context.chat_server().do_send(SendComment { op: UserOperation::CreateCommentLike, comment: res, my_id: None, }); - announce_if_community_is_local(dislike, &user, client, pool).await?; + announce_if_community_is_local(dislike, &user, context).await?; Ok(HttpResponse::Ok().finish()) } diff --git a/server/src/apub/inbox/activities/like.rs b/server/src/apub/inbox/activities/like.rs index b82f5f72c..804c33c39 100644 --- a/server/src/apub/inbox/activities/like.rs +++ b/server/src/apub/inbox/activities/like.rs @@ -11,16 +11,15 @@ use crate::{ PageExt, }, blocking, - routes::ChatServerParam, websocket::{ server::{SendComment, SendPost}, UserOperation, }, - DbPool, + LemmyContext, LemmyError, }; use activitystreams::{activity::Like, base::AnyBase, object::Note, prelude::*}; -use actix_web::{client::Client, HttpResponse}; +use actix_web::HttpResponse; use anyhow::Context; use lemmy_db::{ comment::{CommentForm, CommentLike, CommentLikeForm}, @@ -33,31 +32,24 @@ use lemmy_utils::location_info; pub async fn receive_like( activity: AnyBase, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let like = Like::from_any_base(activity)?.context(location_info!())?; match like.object().as_single_kind_str() { - Some("Page") => receive_like_post(like, client, pool, chat_server).await, - Some("Note") => receive_like_comment(like, client, pool, chat_server).await, + Some("Page") => receive_like_post(like, context).await, + Some("Note") => receive_like_comment(like, context).await, _ => receive_unhandled_activity(like), } } -async fn receive_like_post( - like: Like, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, -) -> Result { - let user = get_user_from_activity(&like, client, pool).await?; +async fn receive_like_post(like: Like, context: &LemmyContext) -> Result { + let user = get_user_from_activity(&like, context).await?; let page = PageExt::from_any_base(like.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let post = PostForm::from_apub(&page, client, pool, None).await?; + let post = PostForm::from_apub(&page, context, None).await?; - let post_id = get_or_fetch_and_insert_post(&post.get_ap_id()?, client, pool) + let post_id = get_or_fetch_and_insert_post(&post.get_ap_id()?, context) .await? .id; @@ -67,40 +59,41 @@ async fn receive_like_post( score: 1, }; let user_id = user.id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { PostLike::remove(conn, user_id, post_id)?; PostLike::like(conn, &like_form) }) .await??; // Refetch the view - let post_view = blocking(pool, move |conn| PostView::read(conn, post_id, None)).await??; + let post_view = blocking(context.pool(), move |conn| { + PostView::read(conn, post_id, None) + }) + .await??; let res = PostResponse { post: post_view }; - chat_server.do_send(SendPost { + context.chat_server().do_send(SendPost { op: UserOperation::CreatePostLike, post: res, my_id: None, }); - announce_if_community_is_local(like, &user, client, pool).await?; + announce_if_community_is_local(like, &user, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_like_comment( like: Like, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let note = Note::from_any_base(like.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let user = get_user_from_activity(&like, client, pool).await?; + let user = get_user_from_activity(&like, context).await?; - let comment = CommentForm::from_apub(¬e, client, pool, None).await?; + let comment = CommentForm::from_apub(¬e, context, None).await?; - let comment_id = get_or_fetch_and_insert_comment(&comment.get_ap_id()?, client, pool) + let comment_id = get_or_fetch_and_insert_comment(&comment.get_ap_id()?, context) .await? .id; @@ -111,15 +104,17 @@ async fn receive_like_comment( score: 1, }; let user_id = user.id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { CommentLike::remove(conn, user_id, comment_id)?; CommentLike::like(conn, &like_form) }) .await??; // Refetch the view - let comment_view = - blocking(pool, move |conn| CommentView::read(conn, comment_id, None)).await??; + let comment_view = blocking(context.pool(), move |conn| { + CommentView::read(conn, comment_id, None) + }) + .await??; // TODO get those recipient actor ids from somewhere let recipient_ids = vec![]; @@ -129,12 +124,12 @@ async fn receive_like_comment( form_id: None, }; - chat_server.do_send(SendComment { + context.chat_server().do_send(SendComment { op: UserOperation::CreateCommentLike, comment: res, my_id: None, }); - announce_if_community_is_local(like, &user, client, pool).await?; + announce_if_community_is_local(like, &user, context).await?; Ok(HttpResponse::Ok().finish()) } diff --git a/server/src/apub/inbox/activities/remove.rs b/server/src/apub/inbox/activities/remove.rs index 4e93dab8a..6cce26e7d 100644 --- a/server/src/apub/inbox/activities/remove.rs +++ b/server/src/apub/inbox/activities/remove.rs @@ -14,16 +14,15 @@ use crate::{ PageExt, }, blocking, - routes::ChatServerParam, websocket::{ server::{SendComment, SendCommunityRoomMessage, SendPost}, UserOperation, }, - DbPool, + LemmyContext, LemmyError, }; use activitystreams::{activity::Remove, base::AnyBase, object::Note, prelude::*}; -use actix_web::{client::Client, HttpResponse}; +use actix_web::HttpResponse; use anyhow::{anyhow, Context}; use lemmy_db::{ comment::{Comment, CommentForm}, @@ -39,40 +38,36 @@ use lemmy_utils::location_info; pub async fn receive_remove( activity: AnyBase, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let remove = Remove::from_any_base(activity)?.context(location_info!())?; - let actor = get_user_from_activity(&remove, client, pool).await?; + let actor = get_user_from_activity(&remove, context).await?; let community = get_community_id_from_activity(&remove)?; if actor.actor_id()?.domain() != community.domain() { return Err(anyhow!("Remove activities are only allowed on local objects").into()); } match remove.object().as_single_kind_str() { - Some("Page") => receive_remove_post(remove, client, pool, chat_server).await, - Some("Note") => receive_remove_comment(remove, client, pool, chat_server).await, - Some("Group") => receive_remove_community(remove, client, pool, chat_server).await, + Some("Page") => receive_remove_post(remove, context).await, + Some("Note") => receive_remove_comment(remove, context).await, + Some("Group") => receive_remove_community(remove, context).await, _ => receive_unhandled_activity(remove), } } async fn receive_remove_post( remove: Remove, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let mod_ = get_user_from_activity(&remove, client, pool).await?; + let mod_ = get_user_from_activity(&remove, context).await?; let page = PageExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let post_ap_id = PostForm::from_apub(&page, client, pool, None) + let post_ap_id = PostForm::from_apub(&page, context, None) .await? .get_ap_id()?; - let post = get_or_fetch_and_insert_post(&post_ap_id, client, pool).await?; + let post = get_or_fetch_and_insert_post(&post_ap_id, context).await?; let post_form = PostForm { name: post.name.to_owned(), @@ -95,39 +90,43 @@ async fn receive_remove_post( published: None, }; let post_id = post.id; - blocking(pool, move |conn| Post::update(conn, post_id, &post_form)).await??; + blocking(context.pool(), move |conn| { + Post::update(conn, post_id, &post_form) + }) + .await??; // Refetch the view let post_id = post.id; - let post_view = blocking(pool, move |conn| PostView::read(conn, post_id, None)).await??; + let post_view = blocking(context.pool(), move |conn| { + PostView::read(conn, post_id, None) + }) + .await??; let res = PostResponse { post: post_view }; - chat_server.do_send(SendPost { + context.chat_server().do_send(SendPost { op: UserOperation::EditPost, post: res, my_id: None, }); - announce_if_community_is_local(remove, &mod_, client, pool).await?; + announce_if_community_is_local(remove, &mod_, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_remove_comment( remove: Remove, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let mod_ = get_user_from_activity(&remove, client, pool).await?; + let mod_ = get_user_from_activity(&remove, context).await?; let note = Note::from_any_base(remove.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let comment_ap_id = CommentForm::from_apub(¬e, client, pool, None) + let comment_ap_id = CommentForm::from_apub(¬e, context, None) .await? .get_ap_id()?; - let comment = get_or_fetch_and_insert_comment(&comment_ap_id, client, pool).await?; + let comment = get_or_fetch_and_insert_comment(&comment_ap_id, context).await?; let comment_form = CommentForm { content: comment.content.to_owned(), @@ -143,15 +142,17 @@ async fn receive_remove_comment( local: comment.local, }; let comment_id = comment.id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { Comment::update(conn, comment_id, &comment_form) }) .await??; // Refetch the view let comment_id = comment.id; - let comment_view = - blocking(pool, move |conn| CommentView::read(conn, comment_id, None)).await??; + let comment_view = blocking(context.pool(), move |conn| { + CommentView::read(conn, comment_id, None) + }) + .await??; // TODO get those recipient actor ids from somewhere let recipient_ids = vec![]; @@ -161,31 +162,29 @@ async fn receive_remove_comment( form_id: None, }; - chat_server.do_send(SendComment { + context.chat_server().do_send(SendComment { op: UserOperation::EditComment, comment: res, my_id: None, }); - announce_if_community_is_local(remove, &mod_, client, pool).await?; + announce_if_community_is_local(remove, &mod_, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_remove_community( remove: Remove, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let mod_ = get_user_from_activity(&remove, client, pool).await?; + let mod_ = get_user_from_activity(&remove, context).await?; let group = GroupExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let community_actor_id = CommunityForm::from_apub(&group, client, pool, Some(mod_.actor_id()?)) + let community_actor_id = CommunityForm::from_apub(&group, context, Some(mod_.actor_id()?)) .await? .actor_id; - let community = blocking(pool, move |conn| { + let community = blocking(context.pool(), move |conn| { Community::read_from_actor_id(conn, &community_actor_id) }) .await??; @@ -211,14 +210,14 @@ async fn receive_remove_community( }; let community_id = community.id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { Community::update(conn, community_id, &community_form) }) .await??; let community_id = community.id; let res = CommunityResponse { - community: blocking(pool, move |conn| { + community: blocking(context.pool(), move |conn| { CommunityView::read(conn, community_id, None) }) .await??, @@ -226,13 +225,13 @@ async fn receive_remove_community( let community_id = res.community.id; - chat_server.do_send(SendCommunityRoomMessage { + context.chat_server().do_send(SendCommunityRoomMessage { op: UserOperation::EditCommunity, response: res, community_id, my_id: None, }); - announce_if_community_is_local(remove, &mod_, client, pool).await?; + announce_if_community_is_local(remove, &mod_, context).await?; Ok(HttpResponse::Ok().finish()) } diff --git a/server/src/apub/inbox/activities/undo.rs b/server/src/apub/inbox/activities/undo.rs index 4cfcea272..ace15c287 100644 --- a/server/src/apub/inbox/activities/undo.rs +++ b/server/src/apub/inbox/activities/undo.rs @@ -13,12 +13,11 @@ use crate::{ PageExt, }, blocking, - routes::ChatServerParam, websocket::{ server::{SendComment, SendCommunityRoomMessage, SendPost}, UserOperation, }, - DbPool, + LemmyContext, LemmyError, }; use activitystreams::{ @@ -27,7 +26,7 @@ use activitystreams::{ object::Note, prelude::*, }; -use actix_web::{client::Client, HttpResponse}; +use actix_web::HttpResponse; use anyhow::{anyhow, Context}; use lemmy_db::{ comment::{Comment, CommentForm, CommentLike}, @@ -44,16 +43,14 @@ use lemmy_utils::location_info; pub async fn receive_undo( activity: AnyBase, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let undo = Undo::from_any_base(activity)?.context(location_info!())?; match undo.object().as_single_kind_str() { - Some("Delete") => receive_undo_delete(undo, client, pool, chat_server).await, - Some("Remove") => receive_undo_remove(undo, client, pool, chat_server).await, - Some("Like") => receive_undo_like(undo, client, pool, chat_server).await, - Some("Dislike") => receive_undo_dislike(undo, client, pool, chat_server).await, + Some("Delete") => receive_undo_delete(undo, context).await, + Some("Remove") => receive_undo_remove(undo, context).await, + Some("Like") => receive_undo_like(undo, context).await, + Some("Dislike") => receive_undo_dislike(undo, context).await, _ => receive_unhandled_activity(undo), } } @@ -81,9 +78,7 @@ where async fn receive_undo_delete( undo: Undo, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let delete = Delete::from_any_base(undo.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; @@ -93,18 +88,16 @@ async fn receive_undo_delete( .as_single_kind_str() .context(location_info!())?; match type_ { - "Note" => receive_undo_delete_comment(undo, &delete, client, pool, chat_server).await, - "Page" => receive_undo_delete_post(undo, &delete, client, pool, chat_server).await, - "Group" => receive_undo_delete_community(undo, &delete, client, pool, chat_server).await, + "Note" => receive_undo_delete_comment(undo, &delete, context).await, + "Page" => receive_undo_delete_post(undo, &delete, context).await, + "Group" => receive_undo_delete_community(undo, &delete, context).await, d => Err(anyhow!("Undo Delete type {} not supported", d).into()), } } async fn receive_undo_remove( undo: Undo, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let remove = Remove::from_any_base(undo.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; @@ -115,19 +108,14 @@ async fn receive_undo_remove( .as_single_kind_str() .context(location_info!())?; match type_ { - "Note" => receive_undo_remove_comment(undo, &remove, client, pool, chat_server).await, - "Page" => receive_undo_remove_post(undo, &remove, client, pool, chat_server).await, - "Group" => receive_undo_remove_community(undo, &remove, client, pool, chat_server).await, + "Note" => receive_undo_remove_comment(undo, &remove, context).await, + "Page" => receive_undo_remove_post(undo, &remove, context).await, + "Group" => receive_undo_remove_community(undo, &remove, context).await, d => Err(anyhow!("Undo Delete type {} not supported", d).into()), } } -async fn receive_undo_like( - undo: Undo, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, -) -> Result { +async fn receive_undo_like(undo: Undo, context: &LemmyContext) -> Result { let like = Like::from_any_base(undo.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; check_is_undo_valid(&undo, &like)?; @@ -137,17 +125,15 @@ async fn receive_undo_like( .as_single_kind_str() .context(location_info!())?; match type_ { - "Note" => receive_undo_like_comment(undo, &like, client, pool, chat_server).await, - "Page" => receive_undo_like_post(undo, &like, client, pool, chat_server).await, + "Note" => receive_undo_like_comment(undo, &like, context).await, + "Page" => receive_undo_like_post(undo, &like, context).await, d => Err(anyhow!("Undo Delete type {} not supported", d).into()), } } async fn receive_undo_dislike( undo: Undo, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let dislike = Dislike::from_any_base(undo.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; @@ -158,8 +144,8 @@ async fn receive_undo_dislike( .as_single_kind_str() .context(location_info!())?; match type_ { - "Note" => receive_undo_dislike_comment(undo, &dislike, client, pool, chat_server).await, - "Page" => receive_undo_dislike_post(undo, &dislike, client, pool, chat_server).await, + "Note" => receive_undo_dislike_comment(undo, &dislike, context).await, + "Page" => receive_undo_dislike_post(undo, &dislike, context).await, d => Err(anyhow!("Undo Delete type {} not supported", d).into()), } } @@ -167,19 +153,17 @@ async fn receive_undo_dislike( async fn receive_undo_delete_comment( undo: Undo, delete: &Delete, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let user = get_user_from_activity(delete, client, pool).await?; + let user = get_user_from_activity(delete, context).await?; let note = Note::from_any_base(delete.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let comment_ap_id = CommentForm::from_apub(¬e, client, pool, Some(user.actor_id()?)) + let comment_ap_id = CommentForm::from_apub(¬e, context, Some(user.actor_id()?)) .await? .get_ap_id()?; - let comment = get_or_fetch_and_insert_comment(&comment_ap_id, client, pool).await?; + let comment = get_or_fetch_and_insert_comment(&comment_ap_id, context).await?; let comment_form = CommentForm { content: comment.content.to_owned(), @@ -195,15 +179,17 @@ async fn receive_undo_delete_comment( local: comment.local, }; let comment_id = comment.id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { Comment::update(conn, comment_id, &comment_form) }) .await??; // Refetch the view let comment_id = comment.id; - let comment_view = - blocking(pool, move |conn| CommentView::read(conn, comment_id, None)).await??; + let comment_view = blocking(context.pool(), move |conn| { + CommentView::read(conn, comment_id, None) + }) + .await??; // TODO get those recipient actor ids from somewhere let recipient_ids = vec![]; @@ -213,32 +199,30 @@ async fn receive_undo_delete_comment( form_id: None, }; - chat_server.do_send(SendComment { + context.chat_server().do_send(SendComment { op: UserOperation::EditComment, comment: res, my_id: None, }); - announce_if_community_is_local(undo, &user, client, pool).await?; + announce_if_community_is_local(undo, &user, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_undo_remove_comment( undo: Undo, remove: &Remove, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let mod_ = get_user_from_activity(remove, client, pool).await?; + let mod_ = get_user_from_activity(remove, context).await?; let note = Note::from_any_base(remove.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let comment_ap_id = CommentForm::from_apub(¬e, client, pool, None) + let comment_ap_id = CommentForm::from_apub(¬e, context, None) .await? .get_ap_id()?; - let comment = get_or_fetch_and_insert_comment(&comment_ap_id, client, pool).await?; + let comment = get_or_fetch_and_insert_comment(&comment_ap_id, context).await?; let comment_form = CommentForm { content: comment.content.to_owned(), @@ -254,15 +238,17 @@ async fn receive_undo_remove_comment( local: comment.local, }; let comment_id = comment.id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { Comment::update(conn, comment_id, &comment_form) }) .await??; // Refetch the view let comment_id = comment.id; - let comment_view = - blocking(pool, move |conn| CommentView::read(conn, comment_id, None)).await??; + let comment_view = blocking(context.pool(), move |conn| { + CommentView::read(conn, comment_id, None) + }) + .await??; // TODO get those recipient actor ids from somewhere let recipient_ids = vec![]; @@ -272,32 +258,30 @@ async fn receive_undo_remove_comment( form_id: None, }; - chat_server.do_send(SendComment { + context.chat_server().do_send(SendComment { op: UserOperation::EditComment, comment: res, my_id: None, }); - announce_if_community_is_local(undo, &mod_, client, pool).await?; + announce_if_community_is_local(undo, &mod_, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_undo_delete_post( undo: Undo, delete: &Delete, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let user = get_user_from_activity(delete, client, pool).await?; + let user = get_user_from_activity(delete, context).await?; let page = PageExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let post_ap_id = PostForm::from_apub(&page, client, pool, Some(user.actor_id()?)) + let post_ap_id = PostForm::from_apub(&page, context, Some(user.actor_id()?)) .await? .get_ap_id()?; - let post = get_or_fetch_and_insert_post(&post_ap_id, client, pool).await?; + let post = get_or_fetch_and_insert_post(&post_ap_id, context).await?; let post_form = PostForm { name: post.name.to_owned(), @@ -320,40 +304,44 @@ async fn receive_undo_delete_post( published: None, }; let post_id = post.id; - blocking(pool, move |conn| Post::update(conn, post_id, &post_form)).await??; + blocking(context.pool(), move |conn| { + Post::update(conn, post_id, &post_form) + }) + .await??; // Refetch the view let post_id = post.id; - let post_view = blocking(pool, move |conn| PostView::read(conn, post_id, None)).await??; + let post_view = blocking(context.pool(), move |conn| { + PostView::read(conn, post_id, None) + }) + .await??; let res = PostResponse { post: post_view }; - chat_server.do_send(SendPost { + context.chat_server().do_send(SendPost { op: UserOperation::EditPost, post: res, my_id: None, }); - announce_if_community_is_local(undo, &user, client, pool).await?; + announce_if_community_is_local(undo, &user, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_undo_remove_post( undo: Undo, remove: &Remove, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let mod_ = get_user_from_activity(remove, client, pool).await?; + let mod_ = get_user_from_activity(remove, context).await?; let page = PageExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let post_ap_id = PostForm::from_apub(&page, client, pool, None) + let post_ap_id = PostForm::from_apub(&page, context, None) .await? .get_ap_id()?; - let post = get_or_fetch_and_insert_post(&post_ap_id, client, pool).await?; + let post = get_or_fetch_and_insert_post(&post_ap_id, context).await?; let post_form = PostForm { name: post.name.to_owned(), @@ -376,40 +364,44 @@ async fn receive_undo_remove_post( published: None, }; let post_id = post.id; - blocking(pool, move |conn| Post::update(conn, post_id, &post_form)).await??; + blocking(context.pool(), move |conn| { + Post::update(conn, post_id, &post_form) + }) + .await??; // Refetch the view let post_id = post.id; - let post_view = blocking(pool, move |conn| PostView::read(conn, post_id, None)).await??; + let post_view = blocking(context.pool(), move |conn| { + PostView::read(conn, post_id, None) + }) + .await??; let res = PostResponse { post: post_view }; - chat_server.do_send(SendPost { + context.chat_server().do_send(SendPost { op: UserOperation::EditPost, post: res, my_id: None, }); - announce_if_community_is_local(undo, &mod_, client, pool).await?; + announce_if_community_is_local(undo, &mod_, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_undo_delete_community( undo: Undo, delete: &Delete, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let user = get_user_from_activity(delete, client, pool).await?; + let user = get_user_from_activity(delete, context).await?; let group = GroupExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let community_actor_id = CommunityForm::from_apub(&group, client, pool, Some(user.actor_id()?)) + let community_actor_id = CommunityForm::from_apub(&group, context, Some(user.actor_id()?)) .await? .actor_id; - let community = blocking(pool, move |conn| { + let community = blocking(context.pool(), move |conn| { Community::read_from_actor_id(conn, &community_actor_id) }) .await??; @@ -435,14 +427,14 @@ async fn receive_undo_delete_community( }; let community_id = community.id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { Community::update(conn, community_id, &community_form) }) .await??; let community_id = community.id; let res = CommunityResponse { - community: blocking(pool, move |conn| { + community: blocking(context.pool(), move |conn| { CommunityView::read(conn, community_id, None) }) .await??, @@ -450,33 +442,31 @@ async fn receive_undo_delete_community( let community_id = res.community.id; - chat_server.do_send(SendCommunityRoomMessage { + context.chat_server().do_send(SendCommunityRoomMessage { op: UserOperation::EditCommunity, response: res, community_id, my_id: None, }); - announce_if_community_is_local(undo, &user, client, pool).await?; + announce_if_community_is_local(undo, &user, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_undo_remove_community( undo: Undo, remove: &Remove, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let mod_ = get_user_from_activity(remove, client, pool).await?; + let mod_ = get_user_from_activity(remove, context).await?; let group = GroupExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let community_actor_id = CommunityForm::from_apub(&group, client, pool, Some(mod_.actor_id()?)) + let community_actor_id = CommunityForm::from_apub(&group, context, Some(mod_.actor_id()?)) .await? .actor_id; - let community = blocking(pool, move |conn| { + let community = blocking(context.pool(), move |conn| { Community::read_from_actor_id(conn, &community_actor_id) }) .await??; @@ -502,14 +492,14 @@ async fn receive_undo_remove_community( }; let community_id = community.id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { Community::update(conn, community_id, &community_form) }) .await??; let community_id = community.id; let res = CommunityResponse { - community: blocking(pool, move |conn| { + community: blocking(context.pool(), move |conn| { CommunityView::read(conn, community_id, None) }) .await??, @@ -517,43 +507,43 @@ async fn receive_undo_remove_community( let community_id = res.community.id; - chat_server.do_send(SendCommunityRoomMessage { + context.chat_server().do_send(SendCommunityRoomMessage { op: UserOperation::EditCommunity, response: res, community_id, my_id: None, }); - announce_if_community_is_local(undo, &mod_, client, pool).await?; + announce_if_community_is_local(undo, &mod_, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_undo_like_comment( undo: Undo, like: &Like, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let user = get_user_from_activity(like, client, pool).await?; + let user = get_user_from_activity(like, context).await?; let note = Note::from_any_base(like.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let comment = CommentForm::from_apub(¬e, client, pool, None).await?; + let comment = CommentForm::from_apub(¬e, context, None).await?; - let comment_id = get_or_fetch_and_insert_comment(&comment.get_ap_id()?, client, pool) + let comment_id = get_or_fetch_and_insert_comment(&comment.get_ap_id()?, context) .await? .id; let user_id = user.id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { CommentLike::remove(conn, user_id, comment_id) }) .await??; // Refetch the view - let comment_view = - blocking(pool, move |conn| CommentView::read(conn, comment_id, None)).await??; + let comment_view = blocking(context.pool(), move |conn| { + CommentView::read(conn, comment_id, None) + }) + .await??; // TODO get those recipient actor ids from somewhere let recipient_ids = vec![]; @@ -563,59 +553,61 @@ async fn receive_undo_like_comment( form_id: None, }; - chat_server.do_send(SendComment { + context.chat_server().do_send(SendComment { op: UserOperation::CreateCommentLike, comment: res, my_id: None, }); - announce_if_community_is_local(undo, &user, client, pool).await?; + announce_if_community_is_local(undo, &user, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_undo_like_post( undo: Undo, like: &Like, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let user = get_user_from_activity(like, client, pool).await?; + let user = get_user_from_activity(like, context).await?; let page = PageExt::from_any_base(like.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let post = PostForm::from_apub(&page, client, pool, None).await?; + let post = PostForm::from_apub(&page, context, None).await?; - let post_id = get_or_fetch_and_insert_post(&post.get_ap_id()?, client, pool) + let post_id = get_or_fetch_and_insert_post(&post.get_ap_id()?, context) .await? .id; let user_id = user.id; - blocking(pool, move |conn| PostLike::remove(conn, user_id, post_id)).await??; + blocking(context.pool(), move |conn| { + PostLike::remove(conn, user_id, post_id) + }) + .await??; // Refetch the view - let post_view = blocking(pool, move |conn| PostView::read(conn, post_id, None)).await??; + let post_view = blocking(context.pool(), move |conn| { + PostView::read(conn, post_id, None) + }) + .await??; let res = PostResponse { post: post_view }; - chat_server.do_send(SendPost { + context.chat_server().do_send(SendPost { op: UserOperation::CreatePostLike, post: res, my_id: None, }); - announce_if_community_is_local(undo, &user, client, pool).await?; + announce_if_community_is_local(undo, &user, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_undo_dislike_comment( undo: Undo, dislike: &Dislike, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let user = get_user_from_activity(dislike, client, pool).await?; + let user = get_user_from_activity(dislike, context).await?; let note = Note::from_any_base( dislike .object() @@ -625,21 +617,23 @@ async fn receive_undo_dislike_comment( )? .context(location_info!())?; - let comment = CommentForm::from_apub(¬e, client, pool, None).await?; + let comment = CommentForm::from_apub(¬e, context, None).await?; - let comment_id = get_or_fetch_and_insert_comment(&comment.get_ap_id()?, client, pool) + let comment_id = get_or_fetch_and_insert_comment(&comment.get_ap_id()?, context) .await? .id; let user_id = user.id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { CommentLike::remove(conn, user_id, comment_id) }) .await??; // Refetch the view - let comment_view = - blocking(pool, move |conn| CommentView::read(conn, comment_id, None)).await??; + let comment_view = blocking(context.pool(), move |conn| { + CommentView::read(conn, comment_id, None) + }) + .await??; // TODO get those recipient actor ids from somewhere let recipient_ids = vec![]; @@ -649,24 +643,22 @@ async fn receive_undo_dislike_comment( form_id: None, }; - chat_server.do_send(SendComment { + context.chat_server().do_send(SendComment { op: UserOperation::CreateCommentLike, comment: res, my_id: None, }); - announce_if_community_is_local(undo, &user, client, pool).await?; + announce_if_community_is_local(undo, &user, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_undo_dislike_post( undo: Undo, dislike: &Dislike, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let user = get_user_from_activity(dislike, client, pool).await?; + let user = get_user_from_activity(dislike, context).await?; let page = PageExt::from_any_base( dislike .object() @@ -676,26 +668,32 @@ async fn receive_undo_dislike_post( )? .context(location_info!())?; - let post = PostForm::from_apub(&page, client, pool, None).await?; + let post = PostForm::from_apub(&page, context, None).await?; - let post_id = get_or_fetch_and_insert_post(&post.get_ap_id()?, client, pool) + let post_id = get_or_fetch_and_insert_post(&post.get_ap_id()?, context) .await? .id; let user_id = user.id; - blocking(pool, move |conn| PostLike::remove(conn, user_id, post_id)).await??; + blocking(context.pool(), move |conn| { + PostLike::remove(conn, user_id, post_id) + }) + .await??; // Refetch the view - let post_view = blocking(pool, move |conn| PostView::read(conn, post_id, None)).await??; + let post_view = blocking(context.pool(), move |conn| { + PostView::read(conn, post_id, None) + }) + .await??; let res = PostResponse { post: post_view }; - chat_server.do_send(SendPost { + context.chat_server().do_send(SendPost { op: UserOperation::CreatePostLike, post: res, my_id: None, }); - announce_if_community_is_local(undo, &user, client, pool).await?; + announce_if_community_is_local(undo, &user, context).await?; Ok(HttpResponse::Ok().finish()) } diff --git a/server/src/apub/inbox/activities/update.rs b/server/src/apub/inbox/activities/update.rs index 6cc6afc48..0364ebc81 100644 --- a/server/src/apub/inbox/activities/update.rs +++ b/server/src/apub/inbox/activities/update.rs @@ -15,16 +15,15 @@ use crate::{ PageExt, }, blocking, - routes::ChatServerParam, websocket::{ server::{SendComment, SendPost}, UserOperation, }, - DbPool, + LemmyContext, LemmyError, }; use activitystreams::{activity::Update, base::AnyBase, object::Note, prelude::*}; -use actix_web::{client::Client, HttpResponse}; +use actix_web::HttpResponse; use anyhow::Context; use lemmy_db::{ comment::{Comment, CommentForm}, @@ -37,92 +36,93 @@ use lemmy_utils::{location_info, scrape_text_for_mentions}; pub async fn receive_update( activity: AnyBase, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let update = Update::from_any_base(activity)?.context(location_info!())?; // ensure that update and actor come from the same instance - let user = get_user_from_activity(&update, client, pool).await?; + let user = get_user_from_activity(&update, context).await?; update.id(user.actor_id()?.domain().context(location_info!())?)?; match update.object().as_single_kind_str() { - Some("Page") => receive_update_post(update, client, pool, chat_server).await, - Some("Note") => receive_update_comment(update, client, pool, chat_server).await, + Some("Page") => receive_update_post(update, context).await, + Some("Note") => receive_update_comment(update, context).await, _ => receive_unhandled_activity(update), } } async fn receive_update_post( update: Update, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { - let user = get_user_from_activity(&update, client, pool).await?; + let user = get_user_from_activity(&update, context).await?; let page = PageExt::from_any_base(update.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let post = PostForm::from_apub(&page, client, pool, Some(user.actor_id()?)).await?; + let post = PostForm::from_apub(&page, context, Some(user.actor_id()?)).await?; - let original_post_id = get_or_fetch_and_insert_post(&post.get_ap_id()?, client, pool) + let original_post_id = get_or_fetch_and_insert_post(&post.get_ap_id()?, context) .await? .id; - blocking(pool, move |conn| { + blocking(context.pool(), move |conn| { Post::update(conn, original_post_id, &post) }) .await??; // Refetch the view - let post_view = blocking(pool, move |conn| { + let post_view = blocking(context.pool(), move |conn| { PostView::read(conn, original_post_id, None) }) .await??; let res = PostResponse { post: post_view }; - chat_server.do_send(SendPost { + context.chat_server().do_send(SendPost { op: UserOperation::EditPost, post: res, my_id: None, }); - announce_if_community_is_local(update, &user, client, pool).await?; + announce_if_community_is_local(update, &user, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_update_comment( update: Update, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let note = Note::from_any_base(update.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let user = get_user_from_activity(&update, client, pool).await?; + let user = get_user_from_activity(&update, context).await?; - let comment = CommentForm::from_apub(¬e, client, pool, Some(user.actor_id()?)).await?; + let comment = CommentForm::from_apub(¬e, context, Some(user.actor_id()?)).await?; - let original_comment_id = get_or_fetch_and_insert_comment(&comment.get_ap_id()?, client, pool) + let original_comment_id = get_or_fetch_and_insert_comment(&comment.get_ap_id()?, context) .await? .id; - let updated_comment = blocking(pool, move |conn| { + let updated_comment = blocking(context.pool(), move |conn| { Comment::update(conn, original_comment_id, &comment) }) .await??; let post_id = updated_comment.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let mentions = scrape_text_for_mentions(&updated_comment.content); - let recipient_ids = - send_local_notifs(mentions, updated_comment, &user, post, pool, false).await?; + let recipient_ids = send_local_notifs( + mentions, + updated_comment, + &user, + post, + context.pool(), + false, + ) + .await?; // Refetch the view - let comment_view = blocking(pool, move |conn| { + let comment_view = blocking(context.pool(), move |conn| { CommentView::read(conn, original_comment_id, None) }) .await??; @@ -133,12 +133,12 @@ async fn receive_update_comment( form_id: None, }; - chat_server.do_send(SendComment { + context.chat_server().do_send(SendComment { op: UserOperation::EditComment, comment: res, my_id: None, }); - announce_if_community_is_local(update, &user, client, pool).await?; + announce_if_community_is_local(update, &user, context).await?; Ok(HttpResponse::Ok().finish()) } diff --git a/server/src/apub/inbox/community_inbox.rs b/server/src/apub/inbox/community_inbox.rs index 49ba48b84..929b85113 100644 --- a/server/src/apub/inbox/community_inbox.rs +++ b/server/src/apub/inbox/community_inbox.rs @@ -7,7 +7,7 @@ use crate::{ ActorType, }, blocking, - routes::{ChatServerParam, DbPoolParam}, + LemmyContext, LemmyError, }; use activitystreams::{ @@ -15,7 +15,7 @@ use activitystreams::{ base::AnyBase, prelude::*, }; -use actix_web::{client::Client, web, HttpRequest, HttpResponse}; +use actix_web::{web, HttpRequest, HttpResponse}; use anyhow::{anyhow, Context}; use lemmy_db::{ community::{Community, CommunityFollower, CommunityFollowerForm}, @@ -41,14 +41,15 @@ pub async fn community_inbox( request: HttpRequest, input: web::Json, path: web::Path, - db: DbPoolParam, - client: web::Data, - _chat_server: ChatServerParam, + context: web::Data, ) -> Result { let activity = input.into_inner(); let path = path.into_inner(); - let community = blocking(&db, move |conn| Community::read_from_name(&conn, &path)).await??; + let community = blocking(&context.pool(), move |conn| { + Community::read_from_name(&conn, &path) + }) + .await??; if !community.local { return Err( @@ -69,7 +70,7 @@ pub async fn community_inbox( .context(location_info!())?; check_is_apub_id_valid(user_uri)?; - let user = get_or_fetch_and_upsert_user(&user_uri, &client, &db).await?; + let user = get_or_fetch_and_upsert_user(&user_uri, &context).await?; verify(&request, &user)?; @@ -77,11 +78,11 @@ pub async fn community_inbox( let kind = activity.kind().context(location_info!())?; let user_id = user.id; let res = match kind { - ValidTypes::Follow => handle_follow(any_base, user, community, &client, &db).await, - ValidTypes::Undo => handle_undo_follow(any_base, user, community, &db).await, + ValidTypes::Follow => handle_follow(any_base, user, community, &context).await, + ValidTypes::Undo => handle_undo_follow(any_base, user, community, &context).await, }; - insert_activity(user_id, activity.clone(), false, &db).await?; + insert_activity(user_id, activity.clone(), false, context.pool()).await?; res } @@ -91,8 +92,7 @@ async fn handle_follow( activity: AnyBase, user: User_, community: Community, - client: &Client, - db: &DbPoolParam, + context: &LemmyContext, ) -> Result { let follow = Follow::from_any_base(activity)?.context(location_info!())?; let community_follower_form = CommunityFollowerForm { @@ -101,12 +101,12 @@ async fn handle_follow( }; // This will fail if they're already a follower, but ignore the error. - blocking(db, move |conn| { + blocking(&context.pool(), move |conn| { CommunityFollower::follow(&conn, &community_follower_form).ok() }) .await?; - community.send_accept_follow(follow, &client, db).await?; + community.send_accept_follow(follow, context).await?; Ok(HttpResponse::Ok().finish()) } @@ -115,7 +115,7 @@ async fn handle_undo_follow( activity: AnyBase, user: User_, community: Community, - db: &DbPoolParam, + context: &LemmyContext, ) -> Result { let _undo = Undo::from_any_base(activity)?.context(location_info!())?; @@ -125,7 +125,7 @@ async fn handle_undo_follow( }; // This will fail if they aren't a follower, but ignore the error. - blocking(db, move |conn| { + blocking(&context.pool(), move |conn| { CommunityFollower::unfollow(&conn, &community_follower_form).ok() }) .await?; diff --git a/server/src/apub/inbox/shared_inbox.rs b/server/src/apub/inbox/shared_inbox.rs index f971a5072..c9f9324dc 100644 --- a/server/src/apub/inbox/shared_inbox.rs +++ b/server/src/apub/inbox/shared_inbox.rs @@ -20,8 +20,7 @@ use crate::{ }, insert_activity, }, - routes::{ChatServerParam, DbPoolParam}, - DbPool, + LemmyContext, LemmyError, }; use activitystreams::{ @@ -30,7 +29,7 @@ use activitystreams::{ object::AsObject, prelude::*, }; -use actix_web::{client::Client, web, HttpRequest, HttpResponse}; +use actix_web::{web, HttpRequest, HttpResponse}; use anyhow::Context; use lemmy_db::user::User_; use lemmy_utils::location_info; @@ -60,9 +59,7 @@ pub type AcceptedActivities = ActorAndObject; pub async fn shared_inbox( request: HttpRequest, input: web::Json, - client: web::Data, - pool: DbPoolParam, - chat_server: ChatServerParam, + context: web::Data, ) -> Result { let activity = input.into_inner(); @@ -79,23 +76,23 @@ pub async fn shared_inbox( check_is_apub_id_valid(sender)?; check_is_apub_id_valid(&community)?; - let actor = get_or_fetch_and_upsert_actor(sender, &client, &pool).await?; + let actor = get_or_fetch_and_upsert_actor(sender, &context).await?; verify(&request, actor.as_ref())?; let any_base = activity.clone().into_any_base()?; let kind = activity.kind().context(location_info!())?; let res = match kind { - ValidTypes::Announce => receive_announce(any_base, &client, &pool, chat_server).await, - ValidTypes::Create => receive_create(any_base, &client, &pool, chat_server).await, - ValidTypes::Update => receive_update(any_base, &client, &pool, chat_server).await, - ValidTypes::Like => receive_like(any_base, &client, &pool, chat_server).await, - ValidTypes::Dislike => receive_dislike(any_base, &client, &pool, chat_server).await, - ValidTypes::Remove => receive_remove(any_base, &client, &pool, chat_server).await, - ValidTypes::Delete => receive_delete(any_base, &client, &pool, chat_server).await, - ValidTypes::Undo => receive_undo(any_base, &client, &pool, chat_server).await, + ValidTypes::Announce => receive_announce(any_base, &context).await, + ValidTypes::Create => receive_create(any_base, &context).await, + ValidTypes::Update => receive_update(any_base, &context).await, + ValidTypes::Like => receive_like(any_base, &context).await, + ValidTypes::Dislike => receive_dislike(any_base, &context).await, + ValidTypes::Remove => receive_remove(any_base, &context).await, + ValidTypes::Delete => receive_delete(any_base, &context).await, + ValidTypes::Undo => receive_undo(any_base, &context).await, }; - insert_activity(actor.user_id(), activity.clone(), false, &pool).await?; + insert_activity(actor.user_id(), activity.clone(), false, context.pool()).await?; res } @@ -111,15 +108,14 @@ where pub(in crate::apub::inbox) async fn get_user_from_activity( activity: &T, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result where T: AsBase + ActorAndObjectRef, { let actor = activity.actor()?; let user_uri = actor.as_single_xsd_any_uri().context(location_info!())?; - get_or_fetch_and_upsert_user(&user_uri, client, pool).await + get_or_fetch_and_upsert_user(&user_uri, context).await } pub(in crate::apub::inbox) fn get_community_id_from_activity( @@ -142,8 +138,7 @@ where pub(in crate::apub::inbox) async fn announce_if_community_is_local( activity: T, user: &User_, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result<(), LemmyError> where T: AsObject, @@ -162,11 +157,10 @@ where let community_uri = community_followers_uri .to_string() .replace("/followers", ""); - let community = - get_or_fetch_and_upsert_community(&Url::parse(&community_uri)?, client, pool).await?; + let community = get_or_fetch_and_upsert_community(&Url::parse(&community_uri)?, context).await?; if community.local { - do_announce(activity.into_any_base()?, &community, &user, client, pool).await?; + do_announce(activity.into_any_base()?, &community, &user, context).await?; } Ok(()) } diff --git a/server/src/apub/inbox/user_inbox.rs b/server/src/apub/inbox/user_inbox.rs index 66f09afbe..f2a778069 100644 --- a/server/src/apub/inbox/user_inbox.rs +++ b/server/src/apub/inbox/user_inbox.rs @@ -8,9 +8,8 @@ use crate::{ FromApub, }, blocking, - routes::{ChatServerParam, DbPoolParam}, websocket::{server::SendUserRoomMessage, UserOperation}, - DbPool, + LemmyContext, LemmyError, }; use activitystreams::{ @@ -19,7 +18,7 @@ use activitystreams::{ object::Note, prelude::*, }; -use actix_web::{client::Client, web, HttpRequest, HttpResponse}; +use actix_web::{web, HttpRequest, HttpResponse}; use anyhow::Context; use lemmy_db::{ community::{CommunityFollower, CommunityFollowerForm}, @@ -52,9 +51,7 @@ pub async fn user_inbox( request: HttpRequest, input: web::Json, path: web::Path, - client: web::Data, - pool: DbPoolParam, - chat_server: ChatServerParam, + context: web::Data, ) -> Result { let activity = input.into_inner(); let username = path.into_inner(); @@ -67,28 +64,20 @@ pub async fn user_inbox( check_is_apub_id_valid(actor_uri)?; - let actor = get_or_fetch_and_upsert_actor(actor_uri, &client, &pool).await?; + let actor = get_or_fetch_and_upsert_actor(actor_uri, &context).await?; verify(&request, actor.as_ref())?; let any_base = activity.clone().into_any_base()?; let kind = activity.kind().context(location_info!())?; let res = match kind { - ValidTypes::Accept => receive_accept(any_base, username, &client, &pool).await, - ValidTypes::Create => { - receive_create_private_message(any_base, &client, &pool, chat_server).await - } - ValidTypes::Update => { - receive_update_private_message(any_base, &client, &pool, chat_server).await - } - ValidTypes::Delete => { - receive_delete_private_message(any_base, &client, &pool, chat_server).await - } - ValidTypes::Undo => { - receive_undo_delete_private_message(any_base, &client, &pool, chat_server).await - } + ValidTypes::Accept => receive_accept(any_base, username, &context).await, + ValidTypes::Create => receive_create_private_message(any_base, &context).await, + ValidTypes::Update => receive_update_private_message(any_base, &context).await, + ValidTypes::Delete => receive_delete_private_message(any_base, &context).await, + ValidTypes::Undo => receive_undo_delete_private_message(any_base, &context).await, }; - insert_activity(actor.user_id(), activity.clone(), false, &pool).await?; + insert_activity(actor.user_id(), activity.clone(), false, context.pool()).await?; res } @@ -96,8 +85,7 @@ pub async fn user_inbox( async fn receive_accept( activity: AnyBase, username: String, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result { let accept = Accept::from_any_base(activity)?.context(location_info!())?; let community_uri = accept @@ -106,9 +94,12 @@ async fn receive_accept( .single_xsd_any_uri() .context(location_info!())?; - let community = get_or_fetch_and_upsert_community(&community_uri, client, pool).await?; + let community = get_or_fetch_and_upsert_community(&community_uri, context).await?; - let user = blocking(pool, move |conn| User_::read_from_name(conn, &username)).await??; + let user = blocking(&context.pool(), move |conn| { + User_::read_from_name(conn, &username) + }) + .await??; // Now you need to add this to the community follower let community_follower_form = CommunityFollowerForm { @@ -117,7 +108,7 @@ async fn receive_accept( }; // This will fail if they're already a follower - blocking(pool, move |conn| { + blocking(&context.pool(), move |conn| { CommunityFollower::follow(conn, &community_follower_form).ok() }) .await?; @@ -128,9 +119,7 @@ async fn receive_accept( async fn receive_create_private_message( activity: AnyBase, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let create = Create::from_any_base(activity)?.context(location_info!())?; let note = Note::from_any_base( @@ -143,14 +132,14 @@ async fn receive_create_private_message( .context(location_info!())?; let domain = Some(create.id_unchecked().context(location_info!())?.to_owned()); - let private_message = PrivateMessageForm::from_apub(¬e, client, pool, domain).await?; + let private_message = PrivateMessageForm::from_apub(¬e, context, domain).await?; - let inserted_private_message = blocking(pool, move |conn| { + let inserted_private_message = blocking(&context.pool(), move |conn| { PrivateMessage::create(conn, &private_message) }) .await??; - let message = blocking(pool, move |conn| { + let message = blocking(&context.pool(), move |conn| { PrivateMessageView::read(conn, inserted_private_message.id) }) .await??; @@ -159,7 +148,7 @@ async fn receive_create_private_message( let recipient_id = res.message.recipient_id; - chat_server.do_send(SendUserRoomMessage { + context.chat_server().do_send(SendUserRoomMessage { op: UserOperation::CreatePrivateMessage, response: res, recipient_id, @@ -171,9 +160,7 @@ async fn receive_create_private_message( async fn receive_update_private_message( activity: AnyBase, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let update = Update::from_any_base(activity)?.context(location_info!())?; let note = Note::from_any_base( @@ -186,22 +173,22 @@ async fn receive_update_private_message( .context(location_info!())?; let domain = Some(update.id_unchecked().context(location_info!())?.to_owned()); - let private_message_form = PrivateMessageForm::from_apub(¬e, client, pool, domain).await?; + let private_message_form = PrivateMessageForm::from_apub(¬e, context, domain).await?; let private_message_ap_id = private_message_form.ap_id.clone(); - let private_message = blocking(pool, move |conn| { + let private_message = blocking(&context.pool(), move |conn| { PrivateMessage::read_from_apub_id(conn, &private_message_ap_id) }) .await??; let private_message_id = private_message.id; - blocking(pool, move |conn| { + blocking(&context.pool(), move |conn| { PrivateMessage::update(conn, private_message_id, &private_message_form) }) .await??; let private_message_id = private_message.id; - let message = blocking(pool, move |conn| { + let message = blocking(&context.pool(), move |conn| { PrivateMessageView::read(conn, private_message_id) }) .await??; @@ -210,7 +197,7 @@ async fn receive_update_private_message( let recipient_id = res.message.recipient_id; - chat_server.do_send(SendUserRoomMessage { + context.chat_server().do_send(SendUserRoomMessage { op: UserOperation::EditPrivateMessage, response: res, recipient_id, @@ -222,9 +209,7 @@ async fn receive_update_private_message( async fn receive_delete_private_message( activity: AnyBase, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let delete = Delete::from_any_base(activity)?.context(location_info!())?; let note = Note::from_any_base( @@ -237,10 +222,10 @@ async fn receive_delete_private_message( .context(location_info!())?; let domain = Some(delete.id_unchecked().context(location_info!())?.to_owned()); - let private_message_form = PrivateMessageForm::from_apub(¬e, client, pool, domain).await?; + let private_message_form = PrivateMessageForm::from_apub(¬e, context, domain).await?; let private_message_ap_id = private_message_form.ap_id; - let private_message = blocking(pool, move |conn| { + let private_message = blocking(&context.pool(), move |conn| { PrivateMessage::read_from_apub_id(conn, &private_message_ap_id) }) .await??; @@ -258,13 +243,13 @@ async fn receive_delete_private_message( }; let private_message_id = private_message.id; - blocking(pool, move |conn| { + blocking(&context.pool(), move |conn| { PrivateMessage::update(conn, private_message_id, &private_message_form) }) .await??; let private_message_id = private_message.id; - let message = blocking(pool, move |conn| { + let message = blocking(&context.pool(), move |conn| { PrivateMessageView::read(&conn, private_message_id) }) .await??; @@ -273,7 +258,7 @@ async fn receive_delete_private_message( let recipient_id = res.message.recipient_id; - chat_server.do_send(SendUserRoomMessage { + context.chat_server().do_send(SendUserRoomMessage { op: UserOperation::EditPrivateMessage, response: res, recipient_id, @@ -285,9 +270,7 @@ async fn receive_delete_private_message( async fn receive_undo_delete_private_message( activity: AnyBase, - client: &Client, - pool: &DbPool, - chat_server: ChatServerParam, + context: &LemmyContext, ) -> Result { let undo = Undo::from_any_base(activity)?.context(location_info!())?; let delete = Delete::from_any_base(undo.object().as_one().context(location_info!())?.to_owned())? @@ -302,10 +285,10 @@ async fn receive_undo_delete_private_message( .context(location_info!())?; let domain = Some(undo.id_unchecked().context(location_info!())?.to_owned()); - let private_message = PrivateMessageForm::from_apub(¬e, client, pool, domain).await?; + let private_message = PrivateMessageForm::from_apub(¬e, context, domain).await?; let private_message_ap_id = private_message.ap_id.clone(); - let private_message_id = blocking(pool, move |conn| { + let private_message_id = blocking(&context.pool(), move |conn| { PrivateMessage::read_from_apub_id(conn, &private_message_ap_id).map(|pm| pm.id) }) .await??; @@ -322,12 +305,12 @@ async fn receive_undo_delete_private_message( updated: Some(naive_now()), }; - blocking(pool, move |conn| { + blocking(&context.pool(), move |conn| { PrivateMessage::update(conn, private_message_id, &private_message_form) }) .await??; - let message = blocking(pool, move |conn| { + let message = blocking(&context.pool(), move |conn| { PrivateMessageView::read(&conn, private_message_id) }) .await??; @@ -336,7 +319,7 @@ async fn receive_undo_delete_private_message( let recipient_id = res.message.recipient_id; - chat_server.do_send(SendUserRoomMessage { + context.chat_server().do_send(SendUserRoomMessage { op: UserOperation::EditPrivateMessage, response: res, recipient_id, diff --git a/server/src/apub/mod.rs b/server/src/apub/mod.rs index 404bfecbb..dddbd7e04 100644 --- a/server/src/apub/mod.rs +++ b/server/src/apub/mod.rs @@ -18,6 +18,7 @@ use crate::{ request::{retry, RecvError}, routes::webfinger::WebFingerResponse, DbPool, + LemmyContext, LemmyError, }; use activitystreams::{ @@ -162,15 +163,13 @@ pub trait FromApub { /// Converts an object from ActivityPub type to Lemmy internal type. /// /// * `apub` The object to read from - /// * `client` Web client to fetch remote actors with - /// * `pool` Database connection + /// * `context` LemmyContext which holds DB pool, HTTP client etc /// * `expected_domain` If present, ensure that the apub object comes from the same domain as /// this URL /// async fn from_apub( apub: &Self::ApubType, - client: &Client, - pool: &DbPool, + context: &LemmyContext, expected_domain: Option, ) -> Result where @@ -179,42 +178,16 @@ pub trait FromApub { #[async_trait::async_trait(?Send)] pub trait ApubObjectType { - async fn send_create( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError>; - async fn send_update( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError>; - async fn send_delete( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError>; + async fn send_create(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>; + async fn send_update(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>; + async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>; async fn send_undo_delete( &self, creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError>; - async fn send_remove( - &self, - mod_: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError>; - async fn send_undo_remove( - &self, - mod_: &User_, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result<(), LemmyError>; + async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError>; + async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError>; } pub(in crate::apub) fn check_actor_domain( @@ -237,24 +210,10 @@ where #[async_trait::async_trait(?Send)] pub trait ApubLikeableType { - async fn send_like( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError>; - async fn send_dislike( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError>; - async fn send_undo_like( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError>; + async fn send_like(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>; + async fn send_dislike(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>; + async fn send_undo_like(&self, creator: &User_, context: &LemmyContext) + -> Result<(), LemmyError>; } #[async_trait::async_trait(?Send)] @@ -274,49 +233,30 @@ pub trait ActorType { async fn send_follow( &self, follow_actor_id: &Url, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result<(), LemmyError>; async fn send_unfollow( &self, follow_actor_id: &Url, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result<(), LemmyError>; #[allow(unused_variables)] async fn send_accept_follow( &self, follow: Follow, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result<(), LemmyError>; - async fn send_delete( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError>; + async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>; async fn send_undo_delete( &self, creator: &User_, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result<(), LemmyError>; - async fn send_remove( - &self, - mod_: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError>; - async fn send_undo_remove( - &self, - mod_: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError>; + async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError>; + async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError>; /// For a given community, returns the inboxes of all followers. async fn get_follower_inboxes(&self, pool: &DbPool) -> Result, LemmyError>; diff --git a/server/src/apub/post.rs b/server/src/apub/post.rs index da548516b..4f2a83155 100644 --- a/server/src/apub/post.rs +++ b/server/src/apub/post.rs @@ -16,8 +16,8 @@ use crate::{ ToApub, }, blocking, - routes::DbPoolParam, DbPool, + LemmyContext, LemmyError, }; use activitystreams::{ @@ -31,13 +31,12 @@ use activitystreams::{ Undo, Update, }, - context, object::{kind::PageType, Image, Object, Page, Tombstone}, prelude::*, public, }; use activitystreams_ext::Ext1; -use actix_web::{body::Body, client::Client, web, HttpResponse}; +use actix_web::{body::Body, web, HttpResponse}; use anyhow::Context; use lemmy_db::{ community::Community, @@ -57,13 +56,13 @@ pub struct PostQuery { /// Return the post json over HTTP. pub async fn get_apub_post( info: web::Path, - db: DbPoolParam, + context: web::Data, ) -> Result, LemmyError> { let id = info.post_id.parse::()?; - let post = blocking(&db, move |conn| Post::read(conn, id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, id)).await??; if !post.deleted { - Ok(create_apub_response(&post.to_apub(&db).await?)) + Ok(create_apub_response(&post.to_apub(context.pool()).await?)) } else { Ok(create_apub_tombstone_response(&post.to_tombstone()?)) } @@ -87,7 +86,7 @@ impl ToApub for Post { // Not needed when the Post is embedded in a collection (like for community outbox) // TODO: need to set proper context defining sensitive/commentsEnabled fields // https://git.asonix.dog/Aardwolf/activitystreams/issues/5 - .set_context(context()) + .set_context(activitystreams::context()) .set_id(self.ap_id.parse::()?) // Use summary field to be consistent with mastodon content warning. // https://mastodon.xyz/@Louisa/103987265222901387.json @@ -199,8 +198,7 @@ impl FromApub for PostForm { /// Parse an ActivityPub page received from another instance into a Lemmy post. async fn from_apub( page: &PageExt, - client: &Client, - pool: &DbPool, + context: &LemmyContext, expected_domain: Option, ) -> Result { let ext = &page.ext_one; @@ -212,7 +210,7 @@ impl FromApub for PostForm { .as_single_xsd_any_uri() .context(location_info!())?; - let creator = get_or_fetch_and_upsert_user(creator_actor_id, client, pool).await?; + let creator = get_or_fetch_and_upsert_user(creator_actor_id, context).await?; let community_actor_id = page .inner @@ -222,7 +220,7 @@ impl FromApub for PostForm { .as_single_xsd_any_uri() .context(location_info!())?; - let community = get_or_fetch_and_upsert_community(community_actor_id, client, pool).await?; + let community = get_or_fetch_and_upsert_community(community_actor_id, context).await?; let thumbnail_url = match &page.inner.image() { Some(any_image) => Image::from_any_base( @@ -300,20 +298,18 @@ impl FromApub for PostForm { #[async_trait::async_trait(?Send)] impl ApubObjectType for Post { /// Send out information about a newly created post, to the followers of the community. - async fn send_create( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let page = self.to_apub(pool).await?; + async fn send_create(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let page = self.to_apub(context.pool()).await?; let community_id = self.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; let mut create = Create::new(creator.actor_id.to_owned(), page.into_any_base()?); create - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(CreateType::Create)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -323,28 +319,25 @@ impl ApubObjectType for Post { &community, vec![community.get_shared_inbox_url()?], create.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) } /// Send out information about an edited post, to the followers of the community. - async fn send_update( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let page = self.to_apub(pool).await?; + async fn send_update(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let page = self.to_apub(context.pool()).await?; let community_id = self.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; let mut update = Update::new(creator.actor_id.to_owned(), page.into_any_base()?); update - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(UpdateType::Update)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -354,27 +347,24 @@ impl ApubObjectType for Post { &community, vec![community.get_shared_inbox_url()?], update.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) } - async fn send_delete( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let page = self.to_apub(pool).await?; + async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let page = self.to_apub(context.pool()).await?; let community_id = self.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; let mut delete = Delete::new(creator.actor_id.to_owned(), page.into_any_base()?); delete - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(DeleteType::Delete)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -384,8 +374,7 @@ impl ApubObjectType for Post { &community, vec![community.get_shared_inbox_url()?], delete.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) @@ -394,17 +383,19 @@ impl ApubObjectType for Post { async fn send_undo_delete( &self, creator: &User_, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result<(), LemmyError> { - let page = self.to_apub(pool).await?; + let page = self.to_apub(context.pool()).await?; let community_id = self.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; let mut delete = Delete::new(creator.actor_id.to_owned(), page.into_any_base()?); delete - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(DeleteType::Delete)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -412,7 +403,7 @@ impl ApubObjectType for Post { // Undo that fake activity let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?); undo - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(UndoType::Undo)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -422,27 +413,24 @@ impl ApubObjectType for Post { &community, vec![community.get_shared_inbox_url()?], undo.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) } - async fn send_remove( - &self, - mod_: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let page = self.to_apub(pool).await?; + async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let page = self.to_apub(context.pool()).await?; let community_id = self.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; let mut remove = Remove::new(mod_.actor_id.to_owned(), page.into_any_base()?); remove - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(RemoveType::Remove)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -452,27 +440,24 @@ impl ApubObjectType for Post { &community, vec![community.get_shared_inbox_url()?], remove.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) } - async fn send_undo_remove( - &self, - mod_: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let page = self.to_apub(pool).await?; + async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let page = self.to_apub(context.pool()).await?; let community_id = self.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; let mut remove = Remove::new(mod_.actor_id.to_owned(), page.into_any_base()?); remove - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(RemoveType::Remove)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -480,7 +465,7 @@ impl ApubObjectType for Post { // Undo that fake activity let mut undo = Undo::new(mod_.actor_id.to_owned(), remove.into_any_base()?); undo - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(UndoType::Undo)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -490,8 +475,7 @@ impl ApubObjectType for Post { &community, vec![community.get_shared_inbox_url()?], undo.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) @@ -500,20 +484,18 @@ impl ApubObjectType for Post { #[async_trait::async_trait(?Send)] impl ApubLikeableType for Post { - async fn send_like( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let page = self.to_apub(pool).await?; + async fn send_like(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let page = self.to_apub(context.pool()).await?; let community_id = self.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; let mut like = Like::new(creator.actor_id.to_owned(), page.into_any_base()?); like - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(LikeType::Like)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -523,27 +505,24 @@ impl ApubLikeableType for Post { &community, vec![community.get_shared_inbox_url()?], like.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) } - async fn send_dislike( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let page = self.to_apub(pool).await?; + async fn send_dislike(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let page = self.to_apub(context.pool()).await?; let community_id = self.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; let mut dislike = Dislike::new(creator.actor_id.to_owned(), page.into_any_base()?); dislike - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(DislikeType::Dislike)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -553,8 +532,7 @@ impl ApubLikeableType for Post { &community, vec![community.get_shared_inbox_url()?], dislike.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) @@ -563,17 +541,19 @@ impl ApubLikeableType for Post { async fn send_undo_like( &self, creator: &User_, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result<(), LemmyError> { - let page = self.to_apub(pool).await?; + let page = self.to_apub(context.pool()).await?; let community_id = self.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; let mut like = Like::new(creator.actor_id.to_owned(), page.into_any_base()?); like - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(LikeType::Like)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -581,7 +561,7 @@ impl ApubLikeableType for Post { // Undo that fake activity let mut undo = Undo::new(creator.actor_id.to_owned(), like.into_any_base()?); undo - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(UndoType::Undo)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()?]); @@ -591,8 +571,7 @@ impl ApubLikeableType for Post { &community, vec![community.get_shared_inbox_url()?], undo.into_any_base()?, - client, - pool, + context, ) .await?; Ok(()) diff --git a/server/src/apub/private_message.rs b/server/src/apub/private_message.rs index 743a484f2..8e5836885 100644 --- a/server/src/apub/private_message.rs +++ b/server/src/apub/private_message.rs @@ -13,6 +13,7 @@ use crate::{ }, blocking, DbPool, + LemmyContext, LemmyError, }; use activitystreams::{ @@ -23,11 +24,9 @@ use activitystreams::{ Undo, Update, }, - context, object::{kind::NoteType, Note, Tombstone}, prelude::*, }; -use actix_web::client::Client; use anyhow::Context; use lemmy_db::{ private_message::{PrivateMessage, PrivateMessageForm}, @@ -51,7 +50,7 @@ impl ToApub for PrivateMessage { let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??; private_message - .set_context(context()) + .set_context(activitystreams::context()) .set_id(Url::parse(&self.ap_id.to_owned())?) .set_published(convert_datetime(self.published)) .set_content(self.content.to_owned()) @@ -77,8 +76,7 @@ impl FromApub for PrivateMessageForm { /// Parse an ActivityPub note received from another instance into a Lemmy Private message async fn from_apub( note: &Note, - client: &Client, - pool: &DbPool, + context: &LemmyContext, expected_domain: Option, ) -> Result { let creator_actor_id = note @@ -88,14 +86,14 @@ impl FromApub for PrivateMessageForm { .single_xsd_any_uri() .context(location_info!())?; - let creator = get_or_fetch_and_upsert_user(&creator_actor_id, client, pool).await?; + let creator = get_or_fetch_and_upsert_user(&creator_actor_id, context).await?; let recipient_actor_id = note .to() .context(location_info!())? .clone() .single_xsd_any_uri() .context(location_info!())?; - let recipient = get_or_fetch_and_upsert_user(&recipient_actor_id, client, pool).await?; + let recipient = get_or_fetch_and_upsert_user(&recipient_actor_id, context).await?; let ap_id = note.id_unchecked().context(location_info!())?.to_string(); check_is_apub_id_valid(&Url::parse(&ap_id)?)?; @@ -121,124 +119,120 @@ impl FromApub for PrivateMessageForm { #[async_trait::async_trait(?Send)] impl ApubObjectType for PrivateMessage { /// Send out information about a newly created private message - async fn send_create( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let note = self.to_apub(pool).await?; + async fn send_create(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let note = self.to_apub(context.pool()).await?; let recipient_id = self.recipient_id; - let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??; + let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??; let mut create = Create::new(creator.actor_id.to_owned(), note.into_any_base()?); let to = recipient.get_inbox_url()?; create - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(CreateType::Create)?) .set_to(to.clone()); - insert_activity(creator.id, create.clone(), true, pool).await?; + insert_activity(creator.id, create.clone(), true, context.pool()).await?; - send_activity(client, &create.into_any_base()?, creator, vec![to]).await?; + send_activity( + context.client(), + &create.into_any_base()?, + creator, + vec![to], + ) + .await?; Ok(()) } /// Send out information about an edited post, to the followers of the community. - async fn send_update( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let note = self.to_apub(pool).await?; + async fn send_update(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let note = self.to_apub(context.pool()).await?; let recipient_id = self.recipient_id; - let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??; + let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??; let mut update = Update::new(creator.actor_id.to_owned(), note.into_any_base()?); let to = recipient.get_inbox_url()?; update - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(UpdateType::Update)?) .set_to(to.clone()); - insert_activity(creator.id, update.clone(), true, pool).await?; + insert_activity(creator.id, update.clone(), true, context.pool()).await?; - send_activity(client, &update.into_any_base()?, creator, vec![to]).await?; + send_activity( + context.client(), + &update.into_any_base()?, + creator, + vec![to], + ) + .await?; Ok(()) } - async fn send_delete( - &self, - creator: &User_, - client: &Client, - pool: &DbPool, - ) -> Result<(), LemmyError> { - let note = self.to_apub(pool).await?; + async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + let note = self.to_apub(context.pool()).await?; let recipient_id = self.recipient_id; - let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??; + let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??; let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?); let to = recipient.get_inbox_url()?; delete - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(DeleteType::Delete)?) .set_to(to.clone()); - insert_activity(creator.id, delete.clone(), true, pool).await?; + insert_activity(creator.id, delete.clone(), true, context.pool()).await?; - send_activity(client, &delete.into_any_base()?, creator, vec![to]).await?; + send_activity( + context.client(), + &delete.into_any_base()?, + creator, + vec![to], + ) + .await?; Ok(()) } async fn send_undo_delete( &self, creator: &User_, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result<(), LemmyError> { - let note = self.to_apub(pool).await?; + let note = self.to_apub(context.pool()).await?; let recipient_id = self.recipient_id; - let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??; + let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??; let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?); let to = recipient.get_inbox_url()?; delete - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(DeleteType::Delete)?) .set_to(to.clone()); // Undo that fake activity let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?); undo - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(UndoType::Undo)?) .set_to(to.clone()); - insert_activity(creator.id, undo.clone(), true, pool).await?; + insert_activity(creator.id, undo.clone(), true, context.pool()).await?; - send_activity(client, &undo.into_any_base()?, creator, vec![to]).await?; + send_activity(context.client(), &undo.into_any_base()?, creator, vec![to]).await?; Ok(()) } - async fn send_remove( - &self, - _mod_: &User_, - _client: &Client, - _pool: &DbPool, - ) -> Result<(), LemmyError> { + async fn send_remove(&self, _mod_: &User_, _context: &LemmyContext) -> Result<(), LemmyError> { unimplemented!() } async fn send_undo_remove( &self, _mod_: &User_, - _client: &Client, - _pool: &DbPool, + _context: &LemmyContext, ) -> Result<(), LemmyError> { unimplemented!() } diff --git a/server/src/apub/user.rs b/server/src/apub/user.rs index 0baa8cc03..f6225dea2 100644 --- a/server/src/apub/user.rs +++ b/server/src/apub/user.rs @@ -12,8 +12,8 @@ use crate::{ ToApub, }, blocking, - routes::DbPoolParam, DbPool, + LemmyContext, LemmyError, }; use activitystreams::{ @@ -23,12 +23,11 @@ use activitystreams::{ Undo, }, actor::{ApActor, Endpoints, Person}, - context, object::{Image, Tombstone}, prelude::*, }; use activitystreams_ext::Ext1; -use actix_web::{body::Body, client::Client, web, HttpResponse}; +use actix_web::{body::Body, web, HttpResponse}; use anyhow::Context; use lemmy_db::{ naive_now, @@ -52,7 +51,7 @@ impl ToApub for User_ { // TODO go through all these to_string and to_owned() let mut person = Person::new(); person - .set_context(context()) + .set_context(activitystreams::context()) .set_id(Url::parse(&self.actor_id)?) .set_name(self.name.to_owned()) .set_published(convert_datetime(self.published)); @@ -117,80 +116,66 @@ impl ActorType for User_ { async fn send_follow( &self, follow_actor_id: &Url, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result<(), LemmyError> { let mut follow = Follow::new(self.actor_id.to_owned(), follow_actor_id.as_str()); follow - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(FollowType::Follow)?); - let follow_actor = get_or_fetch_and_upsert_actor(follow_actor_id, client, pool).await?; + let follow_actor = get_or_fetch_and_upsert_actor(follow_actor_id, context).await?; let to = follow_actor.get_inbox_url()?; - insert_activity(self.id, follow.clone(), true, pool).await?; + insert_activity(self.id, follow.clone(), true, context.pool()).await?; - send_activity(client, &follow.into_any_base()?, self, vec![to]).await?; + send_activity(context.client(), &follow.into_any_base()?, self, vec![to]).await?; Ok(()) } async fn send_unfollow( &self, follow_actor_id: &Url, - client: &Client, - pool: &DbPool, + context: &LemmyContext, ) -> Result<(), LemmyError> { let mut follow = Follow::new(self.actor_id.to_owned(), follow_actor_id.as_str()); follow - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(FollowType::Follow)?); - let follow_actor = get_or_fetch_and_upsert_actor(follow_actor_id, client, pool).await?; + let follow_actor = get_or_fetch_and_upsert_actor(follow_actor_id, context).await?; let to = follow_actor.get_inbox_url()?; // Undo that fake activity let mut undo = Undo::new(Url::parse(&self.actor_id)?, follow.into_any_base()?); undo - .set_context(context()) + .set_context(activitystreams::context()) .set_id(generate_activity_id(UndoType::Undo)?); - insert_activity(self.id, undo.clone(), true, pool).await?; + insert_activity(self.id, undo.clone(), true, context.pool()).await?; - send_activity(client, &undo.into_any_base()?, self, vec![to]).await?; + send_activity(context.client(), &undo.into_any_base()?, self, vec![to]).await?; Ok(()) } - async fn send_delete( - &self, - _creator: &User_, - _client: &Client, - _pool: &DbPool, - ) -> Result<(), LemmyError> { + async fn send_delete(&self, _creator: &User_, _context: &LemmyContext) -> Result<(), LemmyError> { unimplemented!() } async fn send_undo_delete( &self, _creator: &User_, - _client: &Client, - _pool: &DbPool, + _context: &LemmyContext, ) -> Result<(), LemmyError> { unimplemented!() } - async fn send_remove( - &self, - _creator: &User_, - _client: &Client, - _pool: &DbPool, - ) -> Result<(), LemmyError> { + async fn send_remove(&self, _creator: &User_, _context: &LemmyContext) -> Result<(), LemmyError> { unimplemented!() } async fn send_undo_remove( &self, _creator: &User_, - _client: &Client, - _pool: &DbPool, + _context: &LemmyContext, ) -> Result<(), LemmyError> { unimplemented!() } @@ -198,8 +183,7 @@ impl ActorType for User_ { async fn send_accept_follow( &self, _follow: Follow, - _client: &Client, - _pool: &DbPool, + _context: &LemmyContext, ) -> Result<(), LemmyError> { unimplemented!() } @@ -219,8 +203,7 @@ impl FromApub for UserForm { /// Parse an ActivityPub person received from another instance into a Lemmy user. async fn from_apub( person: &PersonExt, - _: &Client, - _: &DbPool, + _context: &LemmyContext, expected_domain: Option, ) -> Result { let avatar = match person.icon() { @@ -298,13 +281,13 @@ impl FromApub for UserForm { /// Return the user json over HTTP. pub async fn get_apub_user_http( info: web::Path, - db: DbPoolParam, + context: web::Data, ) -> Result, LemmyError> { let user_name = info.into_inner().user_name; - let user = blocking(&db, move |conn| { + let user = blocking(context.pool(), move |conn| { User_::find_by_email_or_username(conn, &user_name) }) .await??; - let u = user.to_apub(&db).await?; + let u = user.to_apub(context.pool()).await?; Ok(create_apub_response(&u)) } diff --git a/server/src/lib.rs b/server/src/lib.rs index ace843818..07ee15d40 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -29,7 +29,11 @@ pub mod routes; pub mod version; pub mod websocket; -use crate::request::{retry, RecvError}; +use crate::{ + request::{retry, RecvError}, + websocket::server::ChatServer, +}; +use actix::Addr; use actix_web::{client::Client, dev::ConnectionInfo}; use anyhow::anyhow; use lemmy_utils::{get_apub_protocol_string, settings::Settings}; @@ -67,6 +71,41 @@ impl std::fmt::Display for LemmyError { impl actix_web::error::ResponseError for LemmyError {} +pub struct LemmyContext { + pub pool: DbPool, + pub chat_server: Addr, + pub client: Client, +} + +impl LemmyContext { + pub fn create(pool: DbPool, chat_server: Addr, client: Client) -> LemmyContext { + LemmyContext { + pool, + chat_server, + client, + } + } + pub fn pool(&self) -> &DbPool { + &self.pool + } + pub fn chat_server(&self) -> &Addr { + &self.chat_server + } + pub fn client(&self) -> &Client { + &self.client + } +} + +impl Clone for LemmyContext { + fn clone(&self) -> Self { + LemmyContext { + pool: self.pool.clone(), + chat_server: self.chat_server.clone(), + client: self.client.clone(), + } + } +} + #[derive(Deserialize, Debug)] pub struct IframelyResponse { title: Option, diff --git a/server/src/main.rs b/server/src/main.rs index daa41447a..f6ce4f096 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -25,6 +25,7 @@ use lemmy_server::{ rate_limit::{rate_limiter::RateLimiter, RateLimit}, routes::*, websocket::server::*, + LemmyContext, LemmyError, }; use lemmy_utils::{settings::Settings, CACHE_CONTROL_REGEX}; @@ -68,9 +69,6 @@ async fn main() -> Result<(), LemmyError> { rate_limiter: Arc::new(Mutex::new(RateLimiter::default())), }; - // Set up websocket server - let server = ChatServer::startup(pool.clone(), rate_limiter.clone(), Client::default()).start(); - println!( "Starting http server at {}:{}", settings.bind, settings.port @@ -78,14 +76,15 @@ async fn main() -> Result<(), LemmyError> { // Create Http server with websocket support HttpServer::new(move || { + let chat_server = + ChatServer::startup(pool.clone(), rate_limiter.clone(), Client::default()).start(); + let context = LemmyContext::create(pool.clone(), chat_server, Client::default()); let settings = Settings::get(); let rate_limiter = rate_limiter.clone(); App::new() .wrap_fn(add_cache_headers) .wrap(middleware::Logger::default()) - .data(pool.clone()) - .data(server.clone()) - .data(Client::default()) + .data(context) // The routes .configure(|cfg| api::config(cfg, &rate_limiter)) .configure(federation::config) diff --git a/server/src/routes/api.rs b/server/src/routes/api.rs index 17e7e591c..1c88ffa24 100644 --- a/server/src/routes/api.rs +++ b/server/src/routes/api.rs @@ -1,10 +1,10 @@ use crate::{ api::{comment::*, community::*, post::*, site::*, user::*, Perform}, rate_limit::RateLimit, - routes::{ChatServerParam, DbPoolParam}, websocket::WebsocketInfo, + LemmyContext, }; -use actix_web::{client::Client, error::ErrorBadRequest, *}; +use actix_web::{error::ErrorBadRequest, *}; use serde::Serialize; pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) { @@ -174,21 +174,19 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) { async fn perform( data: Request, - client: &Client, - db: DbPoolParam, - chat_server: ChatServerParam, + context: web::Data, ) -> Result where Request: Perform, Request: Send + 'static, { let ws_info = WebsocketInfo { - chatserver: chat_server.get_ref().to_owned(), + chatserver: context.chat_server().to_owned(), id: None, }; let res = data - .perform(&db, Some(ws_info), client.clone()) + .perform(&context, Some(ws_info)) .await .map(|json| HttpResponse::Ok().json(json)) .map_err(ErrorBadRequest)?; @@ -197,24 +195,20 @@ where async fn route_get( data: web::Query, - client: web::Data, - db: DbPoolParam, - chat_server: ChatServerParam, + context: web::Data, ) -> Result where Data: Serialize + Send + 'static + Perform, { - perform::(data.0, &client, db, chat_server).await + perform::(data.0, context).await } async fn route_post( data: web::Json, - client: web::Data, - db: DbPoolParam, - chat_server: ChatServerParam, + context: web::Data, ) -> Result where Data: Serialize + Send + 'static + Perform, { - perform::(data.0, &client, db, chat_server).await + perform::(data.0, context).await } diff --git a/server/src/routes/feeds.rs b/server/src/routes/feeds.rs index e81d33b7f..890a458f9 100644 --- a/server/src/routes/feeds.rs +++ b/server/src/routes/feeds.rs @@ -1,11 +1,8 @@ -use crate::{api::claims::Claims, blocking, routes::DbPoolParam, LemmyError}; +use crate::{api::claims::Claims, blocking, LemmyContext, LemmyError}; use actix_web::{error::ErrorBadRequest, *}; use anyhow::anyhow; use chrono::{DateTime, NaiveDateTime, Utc}; -use diesel::{ - r2d2::{ConnectionManager, Pool}, - PgConnection, -}; +use diesel::PgConnection; use lemmy_db::{ comment_view::{ReplyQueryBuilder, ReplyView}, community::Community, @@ -40,12 +37,17 @@ pub fn config(cfg: &mut web::ServiceConfig) { .route("/feeds/all.xml", web::get().to(get_all_feed)); } -async fn get_all_feed(info: web::Query, db: DbPoolParam) -> Result { +async fn get_all_feed( + info: web::Query, + context: web::Data, +) -> Result { let sort_type = get_sort_type(info).map_err(ErrorBadRequest)?; - let rss = blocking(&db, move |conn| get_feed_all_data(conn, &sort_type)) - .await? - .map_err(ErrorBadRequest)?; + let rss = blocking(context.pool(), move |conn| { + get_feed_all_data(conn, &sort_type) + }) + .await? + .map_err(ErrorBadRequest)?; Ok( HttpResponse::Ok() @@ -80,7 +82,7 @@ fn get_feed_all_data(conn: &PgConnection, sort_type: &SortType) -> Result, info: web::Query, - db: web::Data>>, + context: web::Data, ) -> Result { let sort_type = get_sort_type(info).map_err(ErrorBadRequest)?; @@ -94,7 +96,7 @@ async fn get_feed( let param = path.1.to_owned(); - let builder = blocking(&db, move |conn| match request_type { + let builder = blocking(context.pool(), move |conn| match request_type { RequestType::User => get_feed_user(conn, &sort_type, param), RequestType::Community => get_feed_community(conn, &sort_type, param), RequestType::Front => get_feed_front(conn, &sort_type, param), diff --git a/server/src/routes/mod.rs b/server/src/routes/mod.rs index c3987145b..d24b6ca5b 100644 --- a/server/src/routes/mod.rs +++ b/server/src/routes/mod.rs @@ -6,14 +6,3 @@ pub mod index; pub mod nodeinfo; pub mod webfinger; pub mod websocket; - -use crate::websocket::server::ChatServer; -use actix::prelude::*; -use actix_web::*; -use diesel::{ - r2d2::{ConnectionManager, Pool}, - PgConnection, -}; - -pub type DbPoolParam = web::Data>>; -pub type ChatServerParam = web::Data>; diff --git a/server/src/routes/nodeinfo.rs b/server/src/routes/nodeinfo.rs index a18d06ea2..1c81bc544 100644 --- a/server/src/routes/nodeinfo.rs +++ b/server/src/routes/nodeinfo.rs @@ -1,4 +1,4 @@ -use crate::{blocking, routes::DbPoolParam, version, LemmyError}; +use crate::{blocking, version, LemmyContext, LemmyError}; use actix_web::{body::Body, error::ErrorBadRequest, *}; use anyhow::anyhow; use lemmy_db::site_view::SiteView; @@ -26,8 +26,8 @@ async fn node_info_well_known() -> Result, LemmyError> { Ok(HttpResponse::Ok().json(node_info)) } -async fn node_info(db: DbPoolParam) -> Result { - let site_view = blocking(&db, SiteView::read) +async fn node_info(context: web::Data) -> Result { + let site_view = blocking(context.pool(), SiteView::read) .await? .map_err(|_| ErrorBadRequest(LemmyError::from(anyhow!("not_found"))))?; diff --git a/server/src/routes/webfinger.rs b/server/src/routes/webfinger.rs index 81fad6110..57bea713d 100644 --- a/server/src/routes/webfinger.rs +++ b/server/src/routes/webfinger.rs @@ -1,4 +1,4 @@ -use crate::{blocking, routes::DbPoolParam, LemmyError}; +use crate::{blocking, LemmyContext, LemmyError}; use actix_web::{error::ErrorBadRequest, web::Query, *}; use anyhow::anyhow; use lemmy_db::{community::Community, user::User_}; @@ -44,7 +44,7 @@ pub fn config(cfg: &mut web::ServiceConfig) { /// https://radical.town/.well-known/webfinger?resource=acct:felix@radical.town async fn get_webfinger_response( info: Query, - db: DbPoolParam, + context: web::Data, ) -> Result { let community_regex_parsed = WEBFINGER_COMMUNITY_REGEX .captures(&info.resource) @@ -59,7 +59,7 @@ async fn get_webfinger_response( let url = if let Some(community_name) = community_regex_parsed { let community_name = community_name.as_str().to_owned(); // Make sure the requested community exists. - blocking(&db, move |conn| { + blocking(context.pool(), move |conn| { Community::read_from_name(conn, &community_name) }) .await? @@ -68,10 +68,12 @@ async fn get_webfinger_response( } else if let Some(user_name) = user_regex_parsed { let user_name = user_name.as_str().to_owned(); // Make sure the requested user exists. - blocking(&db, move |conn| User_::read_from_name(conn, &user_name)) - .await? - .map_err(|_| ErrorBadRequest(LemmyError::from(anyhow!("not_found"))))? - .actor_id + blocking(context.pool(), move |conn| { + User_::read_from_name(conn, &user_name) + }) + .await? + .map_err(|_| ErrorBadRequest(LemmyError::from(anyhow!("not_found"))))? + .actor_id } else { return Err(ErrorBadRequest(LemmyError::from(anyhow!("not_found")))); }; diff --git a/server/src/routes/websocket.rs b/server/src/routes/websocket.rs index 2f964d431..7c787d66d 100644 --- a/server/src/routes/websocket.rs +++ b/server/src/routes/websocket.rs @@ -1,6 +1,7 @@ use crate::{ get_ip, websocket::server::{ChatServer, *}, + LemmyContext, }; use actix::prelude::*; use actix_web::*; @@ -17,11 +18,11 @@ const CLIENT_TIMEOUT: Duration = Duration::from_secs(10); pub async fn chat_route( req: HttpRequest, stream: web::Payload, - chat_server: web::Data>, + context: web::Data, ) -> Result { ws::start( WSSession { - cs_addr: chat_server.get_ref().to_owned(), + cs_addr: context.chat_server().to_owned(), id: 0, hb: Instant::now(), ip: get_ip(&req.connection_info()), diff --git a/server/src/websocket/server.rs b/server/src/websocket/server.rs index a83e4d109..bfc55f637 100644 --- a/server/src/websocket/server.rs +++ b/server/src/websocket/server.rs @@ -9,13 +9,13 @@ use crate::{ websocket::UserOperation, CommunityId, ConnectionId, - DbPool, IPAddr, + LemmyContext, LemmyError, PostId, UserId, }; -use actix_web::client::Client; +use actix_web::{client::Client, web}; use anyhow::Context as acontext; use lemmy_db::naive_now; use lemmy_utils::location_info; @@ -465,11 +465,14 @@ impl ChatServer { let user_operation: UserOperation = UserOperation::from_str(&op)?; - let args = Args { - client, + let context = LemmyContext { pool, + chat_server: addr, + client, + }; + let args = Args { + context: &context, rate_limiter, - chatserver: addr, id: msg.id, ip, op: user_operation.clone(), @@ -562,10 +565,8 @@ impl ChatServer { } struct Args<'a> { - client: Client, - pool: DbPool, + context: &'a LemmyContext, rate_limiter: RateLimit, - chatserver: Addr, id: ConnectionId, ip: IPAddr, op: UserOperation, @@ -578,10 +579,8 @@ where Data: Perform, { let Args { - client, - pool, + context, rate_limiter, - chatserver, id, ip, op, @@ -589,18 +588,18 @@ where } = args; let ws_info = WebsocketInfo { - chatserver, + chatserver: context.chat_server().to_owned(), id: Some(id), }; let data = data.to_string(); let op2 = op.clone(); - let client = client.clone(); let fut = async move { - let pool = pool.clone(); let parsed_data: Data = serde_json::from_str(&data)?; - let res = parsed_data.perform(&pool, Some(ws_info), client).await?; + let res = parsed_data + .perform(&web::Data::new(context.to_owned()), Some(ws_info)) + .await?; to_json_string(&op, &res) };