Skip to content

Federate community reports, and send report create/update/resolve activities to report creator's instance #5496

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 60 commits into from
May 27, 2025

Conversation

dullbananas
Copy link
Collaborator

@dullbananas dullbananas commented Mar 11, 2025

Closes #4897

@dullbananas dullbananas marked this pull request as ready for review March 18, 2025 04:23
}
})
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can directly use Either via get dependency in Cargo.toml:

activitypub_federation = { 
  git = "https://github.com/LemmyNet/activitypub-federation-rust.git", 
  branch = "object-either", 
  default-features = false, 
  features = [
  "actix-web",
] }

@@ -107,13 +107,57 @@ impl Object for SiteOrCommunity {
}
}

impl Actor for SiteOrCommunity {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also implemented Either for Actor.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that mean this should come after LemmyNet/activitypub-federation-rust#139, or that its just something to keep in mind.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -107,13 +107,57 @@ impl Object for SiteOrCommunity {
}
}

impl Actor for SiteOrCommunity {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that mean this should come after LemmyNet/activitypub-federation-rust#139, or that its just something to keep in mind.

) -> LemmyResult<()> {
// admin action comes from the correct instance, so it was presumably done
// by an instance admin.
// TODO: federate instance admin status and check it here
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this would need to be skipped until we federate admins?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We currently assume that any user who is on the same instance as a user or community can perform admin actions on them. This is also in the existing code. It works fine because the remote Lemmy instance performs its own permission checks, and admin actions only federate for users/communities from the same instance.

@dessalines
Copy link
Member

Just needs above comments addressed, and conflicts, then we can merge.

) -> LemmyResult<Either<ApubSite, ApubCommunity>> {
let receiver = self.to[0].dereference(context).await?;
Ok(receiver)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesnt need a separate function.

@@ -91,7 +91,7 @@ impl InCommunity for AnnouncableActivities {
LockPost(a) => a.community(context).await,
UndoLockPost(a) => a.community(context).await,
Report(a) => a.community(context).await,
ResolveReport(a) => a.community(context).await,
ResolveReport(a) => a.object.community(context).await,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, we can probably remove InCommunity impls for all the Undo activities in this way too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might wanna make an issue for that so you don't forget.

let admin = admin_id.dereference(context).await?;
let local_user_view = LocalUserView::read_person(&mut context.pool(), admin.id).await?;
is_admin(&local_user_view)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is only called once inside of verify_mod_or_admin_action so you can move the logic directly there.

@@ -98,6 +102,17 @@ pub(crate) async fn verify_mod_action(
.await
}

pub(crate) async fn verify_mod_or_admin_action(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub(crate) async fn verify_mod_or_admin_action(
async fn verify_mod_or_admin_action(

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can also be moved down one level into community/mod.rs

inboxes.add_inbox(report_creator_site.inbox_url.into());

Ok(inboxes)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dont see why this needs a new function, you can add the logic into report_inboxes

))! as CommunityReportView
).community_report;
expect(resolvedReport).toBeDefined();
expect(resolvedReport.resolved).toBe(true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the community was not removed then the report should stay unresolved, right?

https://github.com/LemmyNet/lemmy/pull/5496/files#diff-59b565f03f82044908e9c09f294e4a28c6a7e32ef9894527ca70cb027ed0943dR377

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For admins on the report creator's instance, that's close enough to what happens, because it stays in the unresolved reports list. But the updated resolved and resolver fields from the remote instance are preserved, so local admins can still see it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the report is still shown despite being resolved? How can admins hide it then without removing the community?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolving it again will remove it from the list, since the filter checks if the resolver is local.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems unintuitive. Besides the same reasoning could be applied to local reports for remote posts or comments. Its better to keep them all consistent, and make a separate issue/pull request to handle this case.

Comment on lines 374 to 377
// if a local user reported a remote community, and the remote admin chose to not remove it,
// then maybe a local admin wants to do something about it (for example, remove the community
// locally, or block the instance)
resolver_is_local.or(community::removed),
Copy link
Member

@dessalines dessalines May 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the logic referred to above. We should probably remove this check, and not make special cases for community removals.

Either way this should be handled at the apub receiving the resolve report, and if its not sent, then its up to each site to resolve it on their own.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it so reports to remote communities are never listed. Resolve from remote admin is still received, so a future PR can either use or overwrite the stored resolved status.

Opened issue #5697 also.

Copy link
Member

@Nutomic Nutomic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, only a minor thing about using Either::right. I also restarted CI in case that was a random failure.

Comment on lines 282 to 286
// Hide reports of remote communities
query = query.filter(
report_combined::community_report_id
.is_null()
.or(community::local),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We aren't doing this for remote posts or comments, so I don't see why this should be a special case either.

If a federated community gets reported, and resolved, that should get sent out and received, then your below filter should work.

If it doesn't get resolved, then its up to each instance to decide what to do with it, just like comments and posts.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got rid of this filter, so it should now be consistent with posts and comments.

@dullbananas
Copy link
Collaborator Author

If I understand the code correctly, the current behavior for resolve federation is to only send the resolve to the reporter's instance if the community of the reported post or comment has a moderator on the reporter's instance, and this has an effect on what admins see. That seems like a bug. In this PR, I changed the report_inboxes function so it unconditionally sends the resolve activity to the reporter's instance, so that more information is available to filters, which is required for implementing a filter that's similar to @Nothing4You's suggestion. Without changing the report query filters, this means that, in the list of unresolved reports, local admins will never see reports resolved by a remote admin, and I don't know if this is the correct behavior. This makes a difference for anything where filter_violates_instance_rules returns true.

@dessalines
Copy link
Member

In this PR, I changed the report_inboxes function so it unconditionally sends the resolve activity to the reporter's instance, so that more information is available to filters, which is required for implementing a filter that's similar to @Nothing4You's suggestion

Without changing the report query filters, this means that, in the list of unresolved reports, local admins will never see reports resolved by a remote admin, and I don't know if this is the correct behavior. This makes a difference for anything where filter_violates_instance_rules returns true.

This is really complicated to think about...

The only possible attack I see here, is if a community adds a lot of federated mods to a troll instance, and admins there then just resolve every report no matter what. That could be an issue if its really bad content.

Isn't the main thing that we just need to be doing a community.local check for the item reported, both on send and receive? After that's done then it should be safe to send the resolutions out anyway.

@Nutomic
Copy link
Member

Nutomic commented May 23, 2025

Resolve actions are only accepted if they are sent by a mod or admin of the corresponding community/instance. This seems to be checked properly in verify.

The change in report_inboxes to send resolve actions to the original reporter also makes sense. In my opinion we can merge this, and if necessary make adjustments in separate PRs.

@dessalines dessalines merged commit cbf16c4 into LemmyNet:main May 27, 2025
1 check passed
dessalines pushed a commit that referenced this pull request Jun 6, 2025
…ivities to report creator's instance (#5496)

* add calls to submit_activity and use SiteOrCommunity

* add send_activity imports

* use separate CreateReportToSite and SendResolveReportToSite variants

* fix api compile errors

* allow apub Report struct to represent community report

* change argument types of Report::new, Report::send, and report_inboxes

* impl Object for ReportableObjects

* impl Actor for SiteOrCommunity

* change return types of ReportObject::dereference and ReportObject::object_id

* Add verify_person_in_site_or_community

* replace Report::community with Report::recipient to return either site or community, and add SiteOrCommunity::local_community

* fix Report::receive

* fix ResolveReport::send

* fix ResolveReport

* fix match_outgoing_activities

* replace recipient with receiver

* lint

* update cargo.toml files

* start removing new custom enums

* Revert "start removing new custom enums"

This reverts commit 8208c8a.

* remove new trait impls on enums

* change reportableobjects to type alias that uses either

* fix fetcher::report

* find and replace reportableobjects variant names

* delete crates/utils/translations

* remove uses of custom siteorcommunity enum

* clippy

* dont use separate module for reportableobjects

* remove ResolveReport::reciever

* replace match in activity_lists with Report::community

* combine variants for community and site in SendActivityData enum

* add reportCommunity function to shared.ts

* fix rust errors

* lint

* change the condition for community reports when listing unresolved reports

* update lemmy-js-client

* fix pnpm-lock.yaml

* api test

* use same null check that's used elsewhere

* federate report activities to report creator's instance

* Apply suggestions from code review

Co-authored-by: Nutomic <[email protected]>

* remove report_remote_inboxes

* remove Report::receiver

* remove verify_admin_action

* move verify_mod_or_admin_action

* always hide reports of remote communities

* refactor local_community

* remove unconditional hiding of reports of remote communities

---------

Co-authored-by: Nutomic <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add ability to report a community
4 participants