Add columns post.pending, comment.pending (#5499)

* Add columns post.pending, comment.pending

* add comments

* rename migration

* helper method, set not pending on vote received

* rename to federation_pending, add comments

* fix down migration
This commit is contained in:
Nutomic 2025-03-25 10:43:25 +00:00 committed by GitHub
parent 3664f987d3
commit 6aede48c1b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 98 additions and 2 deletions

View file

@ -1,3 +1,4 @@
use crate::community_use_pending;
use activitypub_federation::config::Data;
use actix_web::web::Json;
use lemmy_api_common::{
@ -99,6 +100,7 @@ pub async fn create_comment(
let comment_form = CommentInsertForm {
language_id: Some(language_id),
federation_pending: Some(community_use_pending(&post_view.community, &context).await),
..CommentInsertForm::new(local_user_view.person.id, data.post_id, content.clone())
};

View file

@ -1,3 +1,6 @@
use lemmy_api_common::context::LemmyContext;
use lemmy_db_schema::source::community::{Community, CommunityActions};
pub mod comment;
pub mod community;
pub mod custom_emoji;
@ -7,3 +10,14 @@ pub mod private_message;
pub mod site;
pub mod tagline;
pub mod user;
/// Only mark new posts/comments to remote community as pending if it has any local followers.
/// Otherwise it could never get updated to be marked as published.
async fn community_use_pending(community: &Community, context: &LemmyContext) -> bool {
if community.local {
return false;
}
CommunityActions::check_has_local_followers(&mut context.pool(), community.id)
.await
.is_ok()
}

View file

@ -1,4 +1,5 @@
use super::convert_published_time;
use crate::community_use_pending;
use activitypub_federation::config::Data;
use actix_web::web::Json;
use lemmy_api_common::{
@ -112,6 +113,7 @@ pub async fn create_post(
alt_text: data.alt_text.clone(),
nsfw,
language_id: Some(language_id),
federation_pending: Some(community_use_pending(&community, &context).await),
scheduled_publish_time,
..PostInsertForm::new(
data.name.trim().to_string(),

View file

@ -61,6 +61,7 @@ async fn vote_comment(
let comment_id = comment.id;
let like_form = CommentLikeForm::new(actor.id, comment_id, vote_type.into());
let person_id = actor.id;
comment.set_not_pending(&mut context.pool()).await?;
CommentActions::remove_like(&mut context.pool(), person_id, comment_id).await?;
CommentActions::like(&mut context.pool(), &like_form).await?;
Ok(())
@ -75,6 +76,7 @@ async fn vote_post(
let post_id = post.id;
let like_form = PostLikeForm::new(post.id, actor.id, vote_type.into());
let person_id = actor.id;
post.set_not_pending(&mut context.pool()).await?;
PostActions::remove_like(&mut context.pool(), person_id, post_id).await?;
PostActions::like(&mut context.pool(), &like_form).await?;
Ok(())

View file

@ -145,7 +145,12 @@ impl Object for ApubComment {
context,
))
.await?;
verify_is_remote_object(&note.id, context)?;
if let Err(e) = verify_is_remote_object(&note.id, context) {
if let Ok(comment) = note.id.dereference_local(context).await {
comment.set_not_pending(&mut context.pool()).await?;
}
return Err(e.into());
}
Box::pin(verify_person_in_community(
&note.attributed_to,
&community,
@ -196,6 +201,7 @@ impl Object for ApubComment {
distinguished: note.distinguished,
local: Some(false),
language_id,
federation_pending: Some(false),
};
let parent_comment_path = parent_comment.map(|t| t.0.path);
let timestamp: DateTime<Utc> = note.updated.or(note.published).unwrap_or_else(Utc::now);

View file

@ -163,7 +163,12 @@ impl Object for ApubPost {
context: &Data<Self::DataType>,
) -> LemmyResult<()> {
verify_domains_match(page.id.inner(), expected_domain)?;
verify_is_remote_object(&page.id, context)?;
if let Err(e) = verify_is_remote_object(&page.id, context) {
if let Ok(post) = page.id.dereference_local(context).await {
post.set_not_pending(&mut context.pool()).await?;
}
return Err(e.into());
}
let community = page.community(context).await?;
check_apub_id_valid_with_strictness(page.id.inner(), community.local, context).await?;

View file

@ -139,6 +139,18 @@ impl Comment {
let domain = settings.get_protocol_and_hostname();
Ok(Url::parse(&format!("{domain}/comment/{}", self.id))?.into())
}
/// The comment was created locally and sent back, indicating that the community accepted it
pub async fn set_not_pending(&self, pool: &mut DbPool<'_>) -> LemmyResult<()> {
if self.local && self.federation_pending {
let form = CommentUpdateForm {
federation_pending: Some(false),
..Default::default()
};
Comment::update(pool, self.id, &form).await?;
}
Ok(())
}
}
impl Crud for Comment {
@ -301,6 +313,7 @@ mod tests {
hot_rank: RANK_DEFAULT,
report_count: 0,
unresolved_report_count: 0,
federation_pending: false,
};
let child_comment_form = CommentInsertForm::new(

View file

@ -319,6 +319,18 @@ impl Post {
let domain = settings.get_protocol_and_hostname();
Ok(Url::parse(&format!("{domain}/post/{}", self.id))?.into())
}
/// The comment was created locally and sent back, indicating that the community accepted it
pub async fn set_not_pending(&self, pool: &mut DbPool<'_>) -> LemmyResult<()> {
if self.local && self.federation_pending {
let form = PostUpdateForm {
federation_pending: Some(false),
..Default::default()
};
Post::update(pool, self.id, &form).await?;
}
Ok(())
}
}
impl Likeable for PostActions {
@ -624,6 +636,7 @@ mod tests {
report_count: 0,
scaled_rank: RANK_DEFAULT,
unresolved_report_count: 0,
federation_pending: false,
};
// Post Like

View file

@ -138,6 +138,7 @@ diesel::table! {
controversy_rank -> Float8,
report_count -> Int2,
unresolved_report_count -> Int2,
federation_pending -> Bool,
}
}
@ -861,6 +862,7 @@ diesel::table! {
scaled_rank -> Float8,
report_count -> Int2,
unresolved_report_count -> Int2,
federation_pending -> Bool,
}
}

View file

@ -60,6 +60,9 @@ pub struct Comment {
pub controversy_rank: f64,
pub report_count: i16,
pub unresolved_report_count: i16,
/// If a local user comments in a remote community, the comment is hidden until it is confirmed
/// accepted by the community (by receiving it back via federation).
pub federation_pending: bool,
}
#[derive(Debug, Clone, derive_new::new)]
@ -85,6 +88,8 @@ pub struct CommentInsertForm {
pub distinguished: Option<bool>,
#[new(default)]
pub language_id: Option<LanguageId>,
#[new(default)]
pub federation_pending: Option<bool>,
}
#[derive(Debug, Clone, Default)]
@ -100,6 +105,7 @@ pub struct CommentUpdateForm {
pub local: Option<bool>,
pub distinguished: Option<bool>,
pub language_id: Option<LanguageId>,
pub federation_pending: Option<bool>,
}
#[skip_serializing_none]

View file

@ -93,6 +93,9 @@ pub struct Post {
pub scaled_rank: f64,
pub report_count: i16,
pub unresolved_report_count: i16,
/// If a local user posts in a remote community, the comment is hidden until it is confirmed
/// accepted by the community (by receiving it back via federation).
pub federation_pending: bool,
}
#[derive(Debug, Clone, derive_new::new)]
@ -142,6 +145,8 @@ pub struct PostInsertForm {
pub alt_text: Option<String>,
#[new(default)]
pub scheduled_publish_time: Option<DateTime<Utc>>,
#[new(default)]
pub federation_pending: Option<bool>,
}
#[derive(Debug, Clone, Default)]
@ -169,6 +174,7 @@ pub struct PostUpdateForm {
pub url_content_type: Option<Option<String>>,
pub alt_text: Option<Option<String>>,
pub scheduled_publish_time: Option<Option<DateTime<Utc>>>,
pub federation_pending: Option<bool>,
}
#[skip_serializing_none]

View file

@ -232,6 +232,11 @@ impl CommentQuery<'_> {
};
query = o.local_user.visible_communities_only(query);
query = query.filter(
comment::federation_pending
.eq(false)
.or(comment::creator_id.nullable().eq(my_person_id)),
);
if !o.local_user.is_admin() {
query = query.filter(

View file

@ -461,6 +461,11 @@ impl<'a> PostQuery<'a> {
};
query = o.local_user.visible_communities_only(query);
query = query.filter(
post::federation_pending
.eq(false)
.or(post::creator_id.nullable().eq(my_person_id)),
);
if !o.local_user.is_admin() {
query = query.filter(

View file

@ -135,6 +135,7 @@ pub(crate) fn comment_select_remove_deletes() -> _ {
comment::controversy_rank,
comment::report_count,
comment::unresolved_report_count,
comment::federation_pending,
)
}

View file

@ -0,0 +1,6 @@
ALTER TABLE post
DROP COLUMN federation_pending;
ALTER TABLE comment
DROP COLUMN federation_pending;

View file

@ -0,0 +1,8 @@
-- When posting to a remote community mark it as pending until it gets announced back to us.
-- This way the posts of banned users wont appear in the community on other instances.
ALTER TABLE post
ADD COLUMN federation_pending boolean NOT NULL DEFAULT FALSE;
ALTER TABLE comment
ADD COLUMN federation_pending boolean NOT NULL DEFAULT FALSE;