From: Felix Ableitner <me@nutomic.com>
Date: Thu, 18 Mar 2021 13:24:29 +0000 (+0100)
Subject: Fix three federation test cases
X-Git-Url: http://these/git/%24%7Bsite.site_view.site.icon?a=commitdiff_plain;h=4f7dca7c2b9916b52393708d4fc8924e167390dd;p=lemmy.git

Fix three federation test cases
---

diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts
index 01befa60..0d1788c6 100644
--- a/api_tests/src/post.spec.ts
+++ b/api_tests/src/post.spec.ts
@@ -23,6 +23,7 @@ import {
   banUserFromSite,
   searchPostLocal,
   banUserFromCommunity,
+  followCommunity,
 } from './shared';
 import { PostView, CommunityView } from 'lemmy-js-client';
 
@@ -169,35 +170,38 @@ test('Sticky a post', async () => {
 });
 
 test('Lock a post', async () => {
+  await followCommunity(alpha, true, betaCommunity.community.id);
   let postRes = await createPost(alpha, betaCommunity.community.id);
 
   // Lock the post
-  let lockedPostRes = await lockPost(alpha, true, postRes.post_view.post);
+  let searchBeta = await searchPost(beta, postRes.post_view.post);
+  let betaPost1 = searchBeta.posts[0];
+  let lockedPostRes = await lockPost(beta, true, betaPost1.post);
   expect(lockedPostRes.post_view.post.locked).toBe(true);
 
-  // Make sure that post is locked on beta
-  let searchBeta = await searchPostLocal(beta, postRes.post_view.post);
-  let betaPost1 = searchBeta.posts[0];
-  expect(betaPost1.post.locked).toBe(true);
+  // Make sure that post is locked on alpha
+  let searchAlpha = await searchPostLocal(alpha, postRes.post_view.post);
+  let alphaPost1 = searchAlpha.posts[0];
+  expect(alphaPost1.post.locked).toBe(true);
 
   // Try to make a new comment there, on alpha
-  let comment: any = await createComment(alpha, postRes.post_view.post.id);
+  let comment: any = await createComment(alpha, alphaPost1.post.id);
   expect(comment['error']).toBe('locked');
 
   // Unlock a post
-  let unlockedPost = await lockPost(alpha, false, postRes.post_view.post);
+  let unlockedPost = await lockPost(beta, false, betaPost1.post);
   expect(unlockedPost.post_view.post.locked).toBe(false);
 
-  // Make sure that post is unlocked on beta
-  let searchBeta2 = await searchPost(beta, postRes.post_view.post);
-  let betaPost2 = searchBeta2.posts[0];
-  expect(betaPost2.community.local).toBe(true);
-  expect(betaPost2.creator.local).toBe(false);
-  expect(betaPost2.post.locked).toBe(false);
+  // Make sure that post is unlocked on alpha
+  let searchAlpha2 = await searchPostLocal(alpha, postRes.post_view.post);
+  let alphaPost2 = searchAlpha2.posts[0];
+  expect(alphaPost2.community.local).toBe(false);
+  expect(alphaPost2.creator.local).toBe(true);
+  expect(alphaPost2.post.locked).toBe(false);
 
-  // Try to create a new comment, on beta
-  let commentBeta = await createComment(beta, betaPost2.post.id);
-  expect(commentBeta).toBeDefined();
+  // Try to create a new comment, on alpha
+  let commentAlpha = await createComment(alpha, alphaPost1.post.id);
+  expect(commentAlpha).toBeDefined();
 });
 
 test('Delete a post', async () => {
diff --git a/crates/apub/src/activities/receive/post.rs b/crates/apub/src/activities/receive/post.rs
index b0582e60..631f9933 100644
--- a/crates/apub/src/activities/receive/post.rs
+++ b/crates/apub/src/activities/receive/post.rs
@@ -75,14 +75,17 @@ pub(crate) async fn receive_update_post(
   // If sticked or locked state was changed, make sure the actor is a mod
   let stickied = page.ext_one.stickied.context(location_info!())?;
   let locked = !page.ext_one.comments_enabled.context(location_info!())?;
-  let mut is_mod_action = false;
+  let mut mod_action_allowed = false;
   if stickied != old_post.stickied || locked != old_post.locked {
     let community = blocking(context.pool(), move |conn| {
       Community::read(conn, old_post.community_id)
     })
     .await??;
-    verify_mod_activity(&update, announce, &community, context).await?;
-    is_mod_action = true;
+    // Only check mod status if the community is local, otherwise we trust that it was sent correctly.
+    if community.local {
+      verify_mod_activity(&update, announce, &community, context).await?;
+    }
+    mod_action_allowed = true;
   }
 
   let post = Post::from_apub(
@@ -90,7 +93,7 @@ pub(crate) async fn receive_update_post(
     context,
     user.actor_id(),
     request_counter,
-    is_mod_action,
+    mod_action_allowed,
   )
   .await?;
 
diff --git a/crates/apub/src/activities/send/community.rs b/crates/apub/src/activities/send/community.rs
index c6c90d50..84d2fced 100644
--- a/crates/apub/src/activities/send/community.rs
+++ b/crates/apub/src/activities/send/community.rs
@@ -165,7 +165,7 @@ impl CommunityType for Community {
       .set_many_contexts(lemmy_context()?)
       .set_id(generate_activity_id(AnnounceType::Announce)?)
       .set_to(public())
-      .set_many_ccs(vec![self.actor_id()]);
+      .set_many_ccs(vec![self.followers_url.clone().into_inner()]);
 
     send_to_community_followers(announce, self, context).await?;
 
diff --git a/crates/apub/src/inbox/user_inbox.rs b/crates/apub/src/inbox/user_inbox.rs
index 3d16403b..7ddb8336 100644
--- a/crates/apub/src/inbox/user_inbox.rs
+++ b/crates/apub/src/inbox/user_inbox.rs
@@ -1,5 +1,6 @@
 use crate::{
   activities::receive::{
+    comment::{receive_create_comment, receive_update_comment},
     community::{
       receive_delete_community,
       receive_remove_community,
@@ -326,6 +327,8 @@ pub async fn receive_announce(
   }
 }
 
+/// Receive either a new private message, or a new comment mention. We distinguish them by checking
+/// whether the activity is public.
 async fn receive_create(
   context: &LemmyContext,
   activity: AnyBase,
@@ -334,9 +337,15 @@ async fn receive_create(
 ) -> Result<(), LemmyError> {
   let create = Create::from_any_base(activity)?.context(location_info!())?;
   verify_activity_domains_valid(&create, &expected_domain, true)?;
-  receive_create_private_message(&context, create, expected_domain, request_counter).await
+  if verify_is_addressed_to_public(&create).is_ok() {
+    receive_create_comment(create, context, request_counter).await
+  } else {
+    receive_create_private_message(&context, create, expected_domain, request_counter).await
+  }
 }
 
+/// Receive either an updated private message, or an updated comment mention. We distinguish
+/// them by checking whether the activity is public.
 async fn receive_update(
   context: &LemmyContext,
   activity: AnyBase,
@@ -345,7 +354,11 @@ async fn receive_update(
 ) -> Result<(), LemmyError> {
   let update = Update::from_any_base(activity)?.context(location_info!())?;
   verify_activity_domains_valid(&update, &expected_domain, true)?;
-  receive_update_private_message(&context, update, expected_domain, request_counter).await
+  if verify_is_addressed_to_public(&update).is_ok() {
+    receive_update_comment(update, context, request_counter).await
+  } else {
+    receive_update_private_message(&context, update, expected_domain, request_counter).await
+  }
 }
 
 async fn receive_delete(
diff --git a/crates/apub/src/objects/comment.rs b/crates/apub/src/objects/comment.rs
index 43bd8659..63f5d9e2 100644
--- a/crates/apub/src/objects/comment.rs
+++ b/crates/apub/src/objects/comment.rs
@@ -99,14 +99,14 @@ impl FromApub for Comment {
     context: &LemmyContext,
     expected_domain: Url,
     request_counter: &mut i32,
-    is_mod_action: bool,
+    mod_action_allowed: bool,
   ) -> Result<Comment, LemmyError> {
     let comment: Comment = get_object_from_apub(
       note,
       context,
       expected_domain,
       request_counter,
-      is_mod_action,
+      mod_action_allowed,
     )
     .await?;
 
@@ -135,7 +135,7 @@ impl FromApubToForm<NoteExt> for CommentForm {
     context: &LemmyContext,
     expected_domain: Url,
     request_counter: &mut i32,
-    _is_mod_action: bool,
+    _mod_action_allowed: bool,
   ) -> Result<CommentForm, LemmyError> {
     let creator_actor_id = &note
       .attributed_to()
diff --git a/crates/apub/src/objects/community.rs b/crates/apub/src/objects/community.rs
index 9ae801b7..73cca5c7 100644
--- a/crates/apub/src/objects/community.rs
+++ b/crates/apub/src/objects/community.rs
@@ -107,14 +107,14 @@ impl FromApub for Community {
     context: &LemmyContext,
     expected_domain: Url,
     request_counter: &mut i32,
-    is_mod_action: bool,
+    mod_action_allowed: bool,
   ) -> Result<Community, LemmyError> {
     let community: Community = get_object_from_apub(
       group,
       context,
       expected_domain,
       request_counter,
-      is_mod_action,
+      mod_action_allowed,
     )
     .await?;
 
@@ -169,7 +169,7 @@ impl FromApubToForm<GroupExt> for CommunityForm {
     context: &LemmyContext,
     expected_domain: Url,
     request_counter: &mut i32,
-    _is_mod_action: bool,
+    _mod_action_allowed: bool,
   ) -> Result<Self, LemmyError> {
     let moderator_uris = fetch_community_mods(context, group, request_counter).await?;
     let creator_uri = moderator_uris.first().context(location_info!())?;
diff --git a/crates/apub/src/objects/mod.rs b/crates/apub/src/objects/mod.rs
index 9f500720..78095e74 100644
--- a/crates/apub/src/objects/mod.rs
+++ b/crates/apub/src/objects/mod.rs
@@ -46,13 +46,13 @@ pub(crate) trait FromApub {
   /// * `apub` The object to read from
   /// * `context` LemmyContext which holds DB pool, HTTP client etc
   /// * `expected_domain` Domain where the object was received from. None in case of mod action.
-  /// * `is_mod_action` True if the object was sent in a mod activity, ignore `expected_domain` in this case
+  /// * `mod_action_allowed` True if the object can be a mod activity, ignore `expected_domain` in this case
   async fn from_apub(
     apub: &Self::ApubType,
     context: &LemmyContext,
     expected_domain: Url,
     request_counter: &mut i32,
-    is_mod_action: bool,
+    mod_action_allowed: bool,
   ) -> Result<Self, LemmyError>
   where
     Self: Sized;
@@ -65,7 +65,7 @@ pub(in crate::objects) trait FromApubToForm<ApubType> {
     context: &LemmyContext,
     expected_domain: Url,
     request_counter: &mut i32,
-    is_mod_action: bool,
+    mod_action_allowed: bool,
   ) -> Result<Self, LemmyError>
   where
     Self: Sized;
diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs
index 92d54264..14b43c6c 100644
--- a/crates/apub/src/objects/post.rs
+++ b/crates/apub/src/objects/post.rs
@@ -118,14 +118,14 @@ impl FromApub for Post {
     context: &LemmyContext,
     expected_domain: Url,
     request_counter: &mut i32,
-    is_mod_action: bool,
+    mod_action_allowed: bool,
   ) -> Result<Post, LemmyError> {
     let post: Post = get_object_from_apub(
       page,
       context,
       expected_domain,
       request_counter,
-      is_mod_action,
+      mod_action_allowed,
     )
     .await?;
     check_object_for_community_or_site_ban(page, post.community_id, context, request_counter)
@@ -141,9 +141,9 @@ impl FromApubToForm<PageExt> for PostForm {
     context: &LemmyContext,
     expected_domain: Url,
     request_counter: &mut i32,
-    is_mod_action: bool,
+    mod_action_allowed: bool,
   ) -> Result<PostForm, LemmyError> {
-    let ap_id = if is_mod_action {
+    let ap_id = if mod_action_allowed {
       let id = page.id_unchecked().context(location_info!())?;
       check_is_apub_id_valid(id)?;
       id.to_owned().into()
diff --git a/crates/apub/src/objects/private_message.rs b/crates/apub/src/objects/private_message.rs
index 93d13503..ea9ae3f6 100644
--- a/crates/apub/src/objects/private_message.rs
+++ b/crates/apub/src/objects/private_message.rs
@@ -77,14 +77,14 @@ impl FromApub for PrivateMessage {
     context: &LemmyContext,
     expected_domain: Url,
     request_counter: &mut i32,
-    is_mod_action: bool,
+    mod_action_allowed: bool,
   ) -> Result<PrivateMessage, LemmyError> {
     get_object_from_apub(
       note,
       context,
       expected_domain,
       request_counter,
-      is_mod_action,
+      mod_action_allowed,
     )
     .await
   }
@@ -97,7 +97,7 @@ impl FromApubToForm<NoteExt> for PrivateMessageForm {
     context: &LemmyContext,
     expected_domain: Url,
     request_counter: &mut i32,
-    _is_mod_action: bool,
+    _mod_action_allowed: bool,
   ) -> Result<PrivateMessageForm, LemmyError> {
     let creator_actor_id = note
       .attributed_to()
diff --git a/crates/apub/src/objects/user.rs b/crates/apub/src/objects/user.rs
index 5b33331b..b6043d31 100644
--- a/crates/apub/src/objects/user.rs
+++ b/crates/apub/src/objects/user.rs
@@ -93,7 +93,7 @@ impl FromApub for User_ {
     context: &LemmyContext,
     expected_domain: Url,
     request_counter: &mut i32,
-    is_mod_action: bool,
+    mod_action_allowed: bool,
   ) -> Result<User_, LemmyError> {
     let user_id = person.id_unchecked().context(location_info!())?.to_owned();
     let domain = user_id.domain().context(location_info!())?;
@@ -109,7 +109,7 @@ impl FromApub for User_ {
         context,
         expected_domain,
         request_counter,
-        is_mod_action,
+        mod_action_allowed,
       )
       .await?;
       let user = blocking(context.pool(), move |conn| User_::upsert(conn, &user_form)).await??;
@@ -125,7 +125,7 @@ impl FromApubToForm<PersonExt> for UserForm {
     _context: &LemmyContext,
     expected_domain: Url,
     _request_counter: &mut i32,
-    _is_mod_action: bool,
+    _mod_action_allowed: bool,
   ) -> Result<Self, LemmyError> {
     let avatar = match person.icon() {
       Some(any_image) => Some(