Implement private communities
See https://github.com/LemmyNet/rfcs/blob/main/0005-private-communities.md
- [x] Add
CommunityVisibility::Private - [x] Change
CommunityFollower.pending(bool) toCommunityFollower.state(Accepted/Pending,ApprovalRequired) - [x] Unit tests to assure only accepted followers and admins can view posts/comments in private communities
- [x] New API endpoints
GET /community/pending_follows/count,GET /community/pending_follows/list,POST /community/pending_follows/approve - [x] API test for the above endpoints
- [x] Federation
- [x] Enabled signed fetch by default to allow fetching content in private communities
- [x] Mark content in private communities as not public, and check this when receiving
- [x] API tests for federation
- [x] Add field
is_new_instancefor/api/v3/community/pending_follows/listitems - [x] Send reject activity if new follower is not accepted
- [ ] ~~Hide private content in RSS feeds~~ (not necessary, already handled via post_view.rs
This is PR is practically finished and ready for review. However there is one more change I would like to make first. At the moment it uses new endpoints GET /community/pending_follows/count, GET /community/pending_follows/list and POST /community/pending_follows/approve. These are practically identical to the endpoints for approving newly registered users which means clients will also have to duplicate a lot of that logic. Instead I want to merge both approval types under a single set of api endpoints, like this:
GET /api/v3/pending/count:
{
"total": 5,
"registrations": 3,
"private_community": 2,
}
GET /api/v3/pending/list
{
"items": [
{
"id": "registration-312",
"type": "registration",
"person": {...},
"data": {
"registration_application": {...}
},
{
"id": "private-community-312",
"type": "private_community",
"person": {...},
"data": {
"community_id": 532,
"is_new_instance": true
}
]
}
POST /api/v3/pending/approve
{
"id": "private-community-312",
"approve": true,
"deny_reason": "no"
}
This way we can avoid duplicate code, and clients dont even need to add explicit support for different types of pending approvals. So it would be relatively easy to implement an approval process for newly created communities, and existing clients would support that automatically. Problem is that pagination would not work very well (https://github.com/LemmyNet/lemmy/issues/2444) but that can be fixed later. Also the private community doesnt have a reject reason. What do you think?
cc @dessalines @SleeplessOne1917 @MV-GH
I know its verbose, but I personally think there are enough differences to justify separate endpoints
- Site registrations are approved by admins, and affect the site, while private community registrations are approved by community mods, and affect the community only.
- Community registrations need the
community_id, so we'd have to force that to be optional if we tried to combine them. - One lives in api_common/site , the other in api_common/community
Site registrations are approved by admins, and affect the site, while private community registrations are approved by community mods, and affect the community only.
The point is that the logic and rendering for both are practically identical. Basically a list of items with approve/deny buttons. Doesnt make sense to duplicate all that, or to write a common wrapper in each client.
Community registrations need the community_id, so we'd have to force that to be optional if we tried to combine them.
Thats no problem, it can go under data. Adjusted the example above.
One lives in api_common/site , the other in api_common/community
Moving structs around is trivial.
I don't fully understand, you want to merge user applications(instance level) and user join private communities endpoints?
But these are different rights? Only admins can approve user registrations and only mods approve private community follows?
Yes but each user would only the applications he has permission to handle. So if a private community mod calls the list endpoint, he will get only follow requests for that community. If an admin calls it, he will get only registration applications. In case an admin also moderates a private community, he will get both types.
The registrationapplication approval also returns a completely different object, the RegistrationApplicationView. So these are not only different inputs, (one requires community id), done on different tables, but should also return different outputs.
Of course Im planning to rework the return types like in the example above. Much of the data is identical, and whats different goes under data to be parsed separately based on type.
Its much easier for front ends to predictably know which type they're receiving via a different endpoint, rather than using an enum or some other data structure that makes you parse the type. This will be unavoidable for #2444 , but those are edge cases where a single array can contain various different types.
That isn't the case here, where you are only receiving a single object after approving.
Alright then lets leave it like this, less work for me :D
Ready for review.
Weird now clippy fails in ci, but it passes locally with the same Rust version.
Found the problem, the ci check for check_diesel_schema was not working correctly and it actually changed schema.rs while running migrations. The thing is with the extra foreign key reference, community_follower isnt joinable to person anymore, so the on clause has to be specified explicity every time.
I fixed one test failure, but now it keeps throwing this error which I cant reproduce locally, and seems completely unrelated.