Skip to content

Commit

Permalink
Add support for local only community (fixes #1576)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nutomic committed Nov 9, 2023
1 parent aaaf174 commit 387c235
Show file tree
Hide file tree
Showing 16 changed files with 59 additions and 33 deletions.
6 changes: 6 additions & 0 deletions crates/api_common/src/community.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ pub struct CreateCommunity {
/// Whether to restrict posting only to moderators.
pub posting_restricted_to_mods: Option<bool>,
pub discussion_languages: Option<Vec<LanguageId>>,
/// A local-only community does not federate its content to other instances, and can only be seen
/// by local authenticated users.
pub local_only: Option<bool>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
Expand Down Expand Up @@ -147,6 +150,9 @@ pub struct EditCommunity {
/// Whether to restrict posting only to moderators.
pub posting_restricted_to_mods: Option<bool>,
pub discussion_languages: Option<Vec<LanguageId>>,
/// A local-only community does not federate its content to other instances, and can only be seen
/// by local authenticated users.
pub local_only: Option<bool>,
}

#[skip_serializing_none]
Expand Down
10 changes: 10 additions & 0 deletions crates/api_common/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,16 @@ fn limit_expire_time(expires: DateTime<Utc>) -> LemmyResult<Option<DateTime<Utc>
}
}

pub fn check_community_valid(community: &Community) -> LemmyResult<()> {
if community.deleted || community.removed {
Err(LemmyErrorType::Deleted)?
}
if community.local_only {
return Err(LemmyErrorType::CouldntFindCommunity.into());
}
Ok(())
}

#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used)]
Expand Down
1 change: 1 addition & 0 deletions crates/api_crud/src/community/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ pub async fn create_community(
.shared_inbox_url(Some(generate_shared_inbox_url(&community_actor_id)?))
.posting_restricted_to_mods(data.posting_restricted_to_mods)
.instance_id(site_view.site.instance_id)
.local_only(data.local_only)
.build();

let inserted_community = Community::create(&mut context.pool(), &community_form)
Expand Down
1 change: 1 addition & 0 deletions crates/api_crud/src/community/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ pub async fn update_community(
banner,
nsfw: data.nsfw,
posting_restricted_to_mods: data.posting_restricted_to_mods,
local_only: data.local_only,
updated: Some(Some(naive_now())),
..Default::default()
};
Expand Down
10 changes: 7 additions & 3 deletions crates/apub/src/http/comment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ use crate::{
};
use activitypub_federation::{config::Data, traits::Object};
use actix_web::{web::Path, HttpResponse};
use lemmy_api_common::context::LemmyContext;
use lemmy_db_schema::{newtypes::CommentId, source::comment::Comment, traits::Crud};
use lemmy_api_common::{context::LemmyContext, utils::check_community_valid};
use lemmy_db_schema::newtypes::CommentId;
use lemmy_db_views::structs::CommentView;
use lemmy_utils::error::LemmyError;
use serde::Deserialize;

Expand All @@ -21,7 +22,10 @@ pub(crate) async fn get_apub_comment(
context: Data<LemmyContext>,
) -> Result<HttpResponse, LemmyError> {
let id = CommentId(info.comment_id.parse::<i32>()?);
let comment: ApubComment = Comment::read(&mut context.pool(), id).await?.into();
let comment_view = CommentView::read(&mut context.pool(), id, None).await?;
check_community_valid(&comment_view.community)?;

let comment: ApubComment = comment_view.comment.into();
if !comment.local {
Ok(redirect_remote_object(&comment.ap_id))
} else if !comment.deleted && !comment.removed {
Expand Down
29 changes: 12 additions & 17 deletions crates/apub/src/http/community.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ use activitypub_federation::{
traits::{Collection, Object},
};
use actix_web::{web, web::Bytes, HttpRequest, HttpResponse};
use lemmy_api_common::context::LemmyContext;
use lemmy_api_common::{context::LemmyContext, utils::check_community_valid};
use lemmy_db_schema::{source::community::Community, traits::ApubActor};
use lemmy_utils::error::{LemmyError, LemmyErrorType};
use lemmy_utils::error::LemmyError;
use serde::Deserialize;

#[derive(Deserialize)]
Expand All @@ -37,13 +37,13 @@ pub(crate) async fn get_apub_community_http(
.await?
.into();

if !community.deleted && !community.removed {
let apub = community.into_json(&context).await?;

create_apub_response(&apub)
} else {
create_apub_tombstone_response(community.actor_id.clone())
if community.deleted || community.removed {
return create_apub_tombstone_response(community.actor_id.clone());
}
check_community_valid(&community)?;

let apub = community.into_json(&context).await?;
create_apub_response(&apub)
}

/// Handler for all incoming receive to community inboxes.
Expand All @@ -66,6 +66,7 @@ pub(crate) async fn get_apub_community_followers(
) -> Result<HttpResponse, LemmyError> {
let community =
Community::read_from_name(&mut context.pool(), &info.community_name, false).await?;
check_community_valid(&community)?;
let followers = ApubCommunityFollower::read_local(&community.into(), &context).await?;
create_apub_response(&followers)
}
Expand All @@ -80,9 +81,7 @@ pub(crate) async fn get_apub_community_outbox(
Community::read_from_name(&mut context.pool(), &info.community_name, false)
.await?
.into();
if community.deleted || community.removed {
Err(LemmyErrorType::Deleted)?
}
check_community_valid(&community)?;
let outbox = ApubCommunityOutbox::read_local(&community, &context).await?;
create_apub_response(&outbox)
}
Expand All @@ -96,9 +95,7 @@ pub(crate) async fn get_apub_community_moderators(
Community::read_from_name(&mut context.pool(), &info.community_name, false)
.await?
.into();
if community.deleted || community.removed {
Err(LemmyErrorType::Deleted)?
}
check_community_valid(&community)?;
let moderators = ApubCommunityModerators::read_local(&community, &context).await?;
create_apub_response(&moderators)
}
Expand All @@ -112,9 +109,7 @@ pub(crate) async fn get_apub_community_featured(
Community::read_from_name(&mut context.pool(), &info.community_name, false)
.await?
.into();
if community.deleted || community.removed {
Err(LemmyErrorType::Deleted)?
}
check_community_valid(&community)?;
let featured = ApubCommunityFeatured::read_local(&community, &context).await?;
create_apub_response(&featured)
}
10 changes: 7 additions & 3 deletions crates/apub/src/http/post.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ use crate::{
};
use activitypub_federation::{config::Data, traits::Object};
use actix_web::{web, HttpResponse};
use lemmy_api_common::context::LemmyContext;
use lemmy_db_schema::{newtypes::PostId, source::post::Post, traits::Crud};
use lemmy_api_common::{context::LemmyContext, utils::check_community_valid};
use lemmy_db_schema::newtypes::PostId;
use lemmy_db_views::structs::PostView;
use lemmy_utils::error::LemmyError;
use serde::Deserialize;

Expand All @@ -21,7 +22,10 @@ pub(crate) async fn get_apub_post(
context: Data<LemmyContext>,
) -> Result<HttpResponse, LemmyError> {
let id = PostId(info.post_id.parse::<i32>()?);
let post: ApubPost = Post::read(&mut context.pool(), id).await?.into();
let post_view = PostView::read(&mut context.pool(), id, None, false).await?;
check_community_valid(&post_view.community)?;

let post: ApubPost = post_view.post.into();
if !post.local {
Ok(redirect_remote_object(&post.ap_id))
} else if !post.deleted && !post.removed {
Expand Down
11 changes: 2 additions & 9 deletions crates/apub/src/protocol/objects/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,11 @@ impl Group {
name: self.preferred_username.clone(),
title: self.name.unwrap_or(self.preferred_username.clone()),
description,
removed: None,
published: self.published,
updated: self.updated,
deleted: Some(false),
nsfw: Some(self.sensitive.unwrap_or(false)),
actor_id: Some(self.id.into()),
local: Some(false),
private_key: None,
hidden: None,
public_key: self.public_key.public_key_pem,
last_refreshed_at: Some(naive_now()),
icon: self.icon.map(|i| i.url.into()),
Expand All @@ -121,6 +117,7 @@ impl Group {
posting_restricted_to_mods: self.posting_restricted_to_mods,
instance_id,
featured_url: self.featured.map(Into::into),
..Default::default()
}
}

Expand All @@ -132,15 +129,10 @@ impl Group {
&None,
&self.source,
)),
removed: None,
published: self.published.map(Into::into),
updated: Some(self.updated.map(Into::into)),
deleted: None,
nsfw: Some(self.sensitive.unwrap_or(false)),
actor_id: Some(self.id.into()),
local: None,
private_key: None,
hidden: None,
public_key: Some(self.public_key.public_key_pem),
last_refreshed_at: Some(naive_now()),
icon: Some(self.icon.map(|i| i.url.into())),
Expand All @@ -151,6 +143,7 @@ impl Group {
moderators_url: self.attributed_to.map(Into::into),
posting_restricted_to_mods: self.posting_restricted_to_mods,
featured_url: self.featured.map(Into::into),
..Default::default()
}
}
}
1 change: 1 addition & 0 deletions crates/db_schema/src/impls/community.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ mod tests {
hidden: false,
posting_restricted_to_mods: false,
instance_id: inserted_instance.id,
local_only: false,
};

let community_follower_form = CommunityFollowerForm {
Expand Down
1 change: 1 addition & 0 deletions crates/db_schema/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ diesel::table! {
moderators_url -> Nullable<Varchar>,
#[max_length = 255]
featured_url -> Nullable<Varchar>,
local_only -> Bool,
}
}

Expand Down
7 changes: 6 additions & 1 deletion crates/db_schema/src/source/community.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,12 @@ pub struct Community {
/// Url where featured posts collection is served over Activitypub
#[serde(skip)]
pub featured_url: Option<DbUrl>,
/// A local-only community does not federate its content to other instances, and can only be seen
/// by local authenticated users.
pub local_only: bool,
}

#[derive(Debug, Clone, TypedBuilder)]
#[derive(Debug, Clone, TypedBuilder, Default)]
#[builder(field_defaults(default))]
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
#[cfg_attr(feature = "full", diesel(table_name = community))]
Expand Down Expand Up @@ -98,6 +101,7 @@ pub struct CommunityInsertForm {
pub posting_restricted_to_mods: Option<bool>,
#[builder(!default)]
pub instance_id: InstanceId,
pub local_only: Option<bool>,
}

#[derive(Debug, Clone, Default)]
Expand Down Expand Up @@ -125,6 +129,7 @@ pub struct CommunityUpdateForm {
pub featured_url: Option<DbUrl>,
pub hidden: Option<bool>,
pub posting_restricted_to_mods: Option<bool>,
pub local_only: Option<bool>,
}

#[derive(PartialEq, Eq, Debug)]
Expand Down
1 change: 1 addition & 0 deletions crates/db_views/src/comment_report_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ mod tests {
moderators_url: inserted_community.moderators_url,
featured_url: inserted_community.featured_url,
instance_id: inserted_instance.id,
local_only: false,
},
creator: Person {
id: inserted_jessica.id,
Expand Down
1 change: 1 addition & 0 deletions crates/db_views/src/comment_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,7 @@ mod tests {
shared_inbox_url: data.inserted_community.shared_inbox_url.clone(),
moderators_url: data.inserted_community.moderators_url.clone(),
featured_url: data.inserted_community.featured_url.clone(),
local_only: false,
},
counts: CommentAggregates {
id: agg.id,
Expand Down
1 change: 1 addition & 0 deletions crates/db_views/src/post_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1460,6 +1460,7 @@ mod tests {
shared_inbox_url: inserted_community.shared_inbox_url.clone(),
moderators_url: inserted_community.moderators_url.clone(),
featured_url: inserted_community.featured_url.clone(),
local_only: false,
},
counts: PostAggregates {
id: agg.id,
Expand Down
1 change: 1 addition & 0 deletions migrations/2023-11-09-100133_local-only-community/down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
alter table community drop column local_only;
1 change: 1 addition & 0 deletions migrations/2023-11-09-100133_local-only-community/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
alter table community add column local_only boolean not null default false;

0 comments on commit 387c235

Please sign in to comment.