diff --git a/crates/api_common/src/comment.rs b/crates/api_common/src/comment.rs index dc2360edd..df3ddbafa 100644 --- a/crates/api_common/src/comment.rs +++ b/crates/api_common/src/comment.rs @@ -24,8 +24,9 @@ pub struct GetComment { #[derive(Debug, Serialize, Deserialize, Clone, Default)] pub struct EditComment { - pub content: String, pub comment_id: CommentId, + pub content: Option, + pub distinguished: Option, pub form_id: Option, pub auth: Sensitive, } diff --git a/crates/api_crud/src/comment/update.rs b/crates/api_crud/src/comment/update.rs index 2a769277a..4939d5abd 100644 --- a/crates/api_crud/src/comment/update.rs +++ b/crates/api_crud/src/comment/update.rs @@ -7,6 +7,7 @@ use lemmy_api_common::{ check_community_deleted_or_removed, check_post_deleted_or_removed, get_local_user_view_from_jwt, + is_mod_or_admin, }, }; use lemmy_apub::protocol::activities::{ @@ -47,6 +48,7 @@ impl PerformCrud for EditComment { CommentView::read(conn, comment_id, None) }) .await??; + let mut updated_comment = orig_comment.comment.clone(); // TODO is this necessary? It should really only need to check on create check_community_ban( @@ -63,15 +65,32 @@ impl PerformCrud for EditComment { return Err(LemmyError::from_message("no_comment_edit_allowed")); } - // Do the update - let content_slurs_removed = - remove_slurs(&data.content.to_owned(), &context.settings().slur_regex()); - let comment_id = data.comment_id; - let updated_comment = blocking(context.pool(), move |conn| { - Comment::update_content(conn, comment_id, &content_slurs_removed) - }) - .await? - .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?; + if let Some(distinguished) = data.distinguished { + // Verify that only a mod or admin can distinguish a comment + is_mod_or_admin( + context.pool(), + local_user_view.person.id, + orig_comment.community.id, + ) + .await?; + + updated_comment = blocking(context.pool(), move |conn| { + Comment::update_distinguished(conn, comment_id, distinguished) + }) + .await? + .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?; + } + + // Update the Content + if let Some(content) = &data.content { + let content_slurs_removed = remove_slurs(content, &context.settings().slur_regex()); + let comment_id = data.comment_id; + updated_comment = blocking(context.pool(), move |conn| { + Comment::update_content(conn, comment_id, &content_slurs_removed) + }) + .await? + .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?; + }; // Do the mentions / recipients let updated_comment_content = updated_comment.content.to_owned(); diff --git a/crates/apub/assets/lemmy/context.json b/crates/apub/assets/lemmy/context.json index 1a0fb07d1..68476585c 100644 --- a/crates/apub/assets/lemmy/context.json +++ b/crates/apub/assets/lemmy/context.json @@ -16,6 +16,7 @@ "@type": "@id", "@id": "lemmy:moderators" }, - "expires": "as:endTime" + "expires": "as:endTime", + "distinguished": "lemmy:distinguished" } ] diff --git a/crates/apub/assets/lemmy/objects/note.json b/crates/apub/assets/lemmy/objects/note.json index 269063a76..44a3b516c 100644 --- a/crates/apub/assets/lemmy/objects/note.json +++ b/crates/apub/assets/lemmy/objects/note.json @@ -21,6 +21,7 @@ "name": "@picard@enterprise.lemmy.ml" } ], + "distinguished": false, "published": "2021-03-01T13:42:43.966208+00:00", "updated": "2021-03-01T13:43:03.955787+00:00" } diff --git a/crates/apub/src/objects/comment.rs b/crates/apub/src/objects/comment.rs index 88b08746c..82601170e 100644 --- a/crates/apub/src/objects/comment.rs +++ b/crates/apub/src/objects/comment.rs @@ -121,6 +121,7 @@ impl ApubObject for ApubComment { published: Some(convert_datetime(self.published)), updated: self.updated.map(convert_datetime), tag: maa.tags, + distinguished: Some(self.distinguished), }; Ok(note) @@ -184,6 +185,7 @@ impl ApubObject for ApubComment { updated: note.updated.map(|u| u.naive_local()), deleted: None, ap_id: Some(note.id.into()), + distinguished: note.distinguished, local: Some(false), }; let parent_comment_path = parent_comment.map(|t| t.0.path); diff --git a/crates/apub/src/protocol/objects/note.rs b/crates/apub/src/protocol/objects/note.rs index 211737377..75fecac79 100644 --- a/crates/apub/src/protocol/objects/note.rs +++ b/crates/apub/src/protocol/objects/note.rs @@ -44,6 +44,8 @@ pub struct Note { pub(crate) updated: Option>, #[serde(default)] pub(crate) tag: Vec, + // lemmy extension + pub(crate) distinguished: Option, } impl Note { diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index f3199c77f..bb6a928b7 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -86,6 +86,17 @@ impl Comment { .get_result::(conn) } + pub fn update_distinguished( + conn: &PgConnection, + comment_id: CommentId, + new_distinguished: bool, + ) -> Result { + use crate::schema::comment::dsl::*; + diesel::update(comment.find(comment_id)) + .set((distinguished.eq(new_distinguished), updated.eq(naive_now()))) + .get_result::(conn) + } + pub fn create( conn: &PgConnection, comment_form: &CommentForm, @@ -330,6 +341,7 @@ mod tests { published: inserted_comment.published, updated: None, ap_id: inserted_comment.ap_id.to_owned(), + distinguished: false, local: true, }; diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 44e8e0bbc..4c2caaf06 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -26,6 +26,7 @@ table! { ap_id -> Varchar, local -> Bool, path -> Ltree, + distinguished -> Bool, } } diff --git a/crates/db_schema/src/source/comment.rs b/crates/db_schema/src/source/comment.rs index 7418d122d..80a71053c 100644 --- a/crates/db_schema/src/source/comment.rs +++ b/crates/db_schema/src/source/comment.rs @@ -22,6 +22,7 @@ pub struct Comment { pub local: bool, #[serde(with = "LtreeDef")] pub path: Ltree, + pub distinguished: bool, } #[derive(Clone, Default)] @@ -37,6 +38,7 @@ pub struct CommentForm { pub deleted: Option, pub ap_id: Option, pub local: Option, + pub distinguished: Option, } #[derive(PartialEq, Debug, Clone)] diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs index 05c6a698c..9fa543d03 100644 --- a/crates/db_views/src/comment_view.rs +++ b/crates/db_views/src/comment_view.rs @@ -531,6 +531,7 @@ mod tests { ap_id: inserted_comment_0.ap_id, updated: None, local: true, + distinguished: false, path: top_path, }, creator: PersonSafe { diff --git a/migrations/2022-08-04-214722_add_distinguished_comment/down.sql b/migrations/2022-08-04-214722_add_distinguished_comment/down.sql new file mode 100644 index 000000000..fff64498e --- /dev/null +++ b/migrations/2022-08-04-214722_add_distinguished_comment/down.sql @@ -0,0 +1 @@ +alter table comment drop column distinguished; diff --git a/migrations/2022-08-04-214722_add_distinguished_comment/up.sql b/migrations/2022-08-04-214722_add_distinguished_comment/up.sql new file mode 100644 index 000000000..a23d2331f --- /dev/null +++ b/migrations/2022-08-04-214722_add_distinguished_comment/up.sql @@ -0,0 +1 @@ +alter table comment add column distinguished boolean not null default false;