Activitypub breaking changes for Lemmy 0.18 (#2705)

* Remove deprecated field `group.moderators`

* Drop column local_site.federation_debug

* Remove backwards compatibility code for feature/lock post

https://github.com/LemmyNet/lemmy/pull/2716

---------

Co-authored-by: Dessalines <dessalines@users.noreply.github.com>
This commit is contained in:
Nutomic 2023-06-07 21:18:17 +02:00 committed by GitHub
parent 1c9f0c2bed
commit 2423b89ced
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 21 additions and 91 deletions

View file

@ -115,7 +115,6 @@ impl PerformCrud for CreateSite {
.slur_filter_regex(diesel_option_overwrite(&data.slur_filter_regex)) .slur_filter_regex(diesel_option_overwrite(&data.slur_filter_regex))
.actor_name_max_length(data.actor_name_max_length) .actor_name_max_length(data.actor_name_max_length)
.federation_enabled(data.federation_enabled) .federation_enabled(data.federation_enabled)
.federation_debug(data.federation_debug)
.federation_worker_count(data.federation_worker_count) .federation_worker_count(data.federation_worker_count)
.captcha_enabled(data.captcha_enabled) .captcha_enabled(data.captcha_enabled)
.captcha_difficulty(data.captcha_difficulty.clone()) .captcha_difficulty(data.captcha_difficulty.clone())

View file

@ -113,7 +113,6 @@ impl PerformCrud for EditSite {
.slur_filter_regex(diesel_option_overwrite(&data.slur_filter_regex)) .slur_filter_regex(diesel_option_overwrite(&data.slur_filter_regex))
.actor_name_max_length(data.actor_name_max_length) .actor_name_max_length(data.actor_name_max_length)
.federation_enabled(data.federation_enabled) .federation_enabled(data.federation_enabled)
.federation_debug(data.federation_debug)
.federation_worker_count(data.federation_worker_count) .federation_worker_count(data.federation_worker_count)
.captcha_enabled(data.captcha_enabled) .captcha_enabled(data.captcha_enabled)
.captcha_difficulty(data.captcha_difficulty.clone()) .captcha_difficulty(data.captcha_difficulty.clone())

View file

@ -12,11 +12,11 @@
"mediaType": "text/markdown" "mediaType": "text/markdown"
}, },
"sensitive": false, "sensitive": false,
"moderators": "http://enterprise.lemmy.ml/c/main/moderators",
"postingRestrictedToMods": false, "postingRestrictedToMods": false,
"inbox": "http://enterprise.lemmy.ml/c/main/inbox", "inbox": "http://enterprise.lemmy.ml/c/main/inbox",
"outbox": "http://enterprise.lemmy.ml/c/main/outbox", "outbox": "http://enterprise.lemmy.ml/c/main/outbox",
"followers": "http://enterprise.lemmy.ml/c/main/followers", "followers": "http://enterprise.lemmy.ml/c/main/followers",
"attributedTo": "https://enterprise.lemmy.ml/c/main/moderators",
"endpoints": { "endpoints": {
"sharedInbox": "http://enterprise.lemmy.ml/inbox" "sharedInbox": "http://enterprise.lemmy.ml/inbox"
}, },

View file

@ -25,7 +25,6 @@
], ],
"commentsEnabled": true, "commentsEnabled": true,
"sensitive": false, "sensitive": false,
"stickied": false,
"language": { "language": {
"identifier": "ko", "identifier": "ko",
"name": "한국어" "name": "한국어"

View file

@ -25,7 +25,6 @@
], ],
"commentsEnabled": true, "commentsEnabled": true,
"sensitive": false, "sensitive": false,
"stickied": false,
"published": "2021-10-29T15:10:51.557399+00:00", "published": "2021-10-29T15:10:51.557399+00:00",
"updated": "2021-10-29T15:11:35.976374+00:00" "updated": "2021-10-29T15:11:35.976374+00:00"
}, },

View file

@ -17,7 +17,6 @@
"attachment": [], "attachment": [],
"commentsEnabled": true, "commentsEnabled": true,
"sensitive": false, "sensitive": false,
"stickied": true,
"published": "2023-02-06T06:42:41.939437+00:00", "published": "2023-02-06T06:42:41.939437+00:00",
"language": { "language": {
"identifier": "de", "identifier": "de",
@ -39,7 +38,6 @@
"attachment": [], "attachment": [],
"commentsEnabled": true, "commentsEnabled": true,
"sensitive": false, "sensitive": false,
"stickied": true,
"published": "2023-02-06T06:42:37.119567+00:00", "published": "2023-02-06T06:42:37.119567+00:00",
"language": { "language": {
"identifier": "de", "identifier": "de",

View file

@ -19,7 +19,6 @@
}, },
"inbox": "https://enterprise.lemmy.ml/c/tenforward/inbox", "inbox": "https://enterprise.lemmy.ml/c/tenforward/inbox",
"followers": "https://enterprise.lemmy.ml/c/tenforward/followers", "followers": "https://enterprise.lemmy.ml/c/tenforward/followers",
"moderators": "https://enterprise.lemmy.ml/c/tenforward/moderators",
"attributedTo": "https://enterprise.lemmy.ml/c/tenforward/moderators", "attributedTo": "https://enterprise.lemmy.ml/c/tenforward/moderators",
"featured": "https://enterprise.lemmy.ml/c/tenforward//featured", "featured": "https://enterprise.lemmy.ml/c/tenforward//featured",
"postingRestrictedToMods": false, "postingRestrictedToMods": false,

View file

@ -26,7 +26,6 @@
}, },
"sensitive": false, "sensitive": false,
"commentsEnabled": true, "commentsEnabled": true,
"stickied": true,
"language": { "language": {
"identifier": "fr", "identifier": "fr",
"name": "Français" "name": "Français"

View file

@ -10,11 +10,7 @@ use crate::{
insert_activity, insert_activity,
objects::{community::ApubCommunity, person::ApubPerson, post::ApubPost}, objects::{community::ApubCommunity, person::ApubPerson, post::ApubPost},
protocol::{ protocol::{
activities::{ activities::community::{collection_add::CollectionAdd, collection_remove::CollectionRemove},
community::{collection_add::CollectionAdd, collection_remove::CollectionRemove},
create_or_update::page::CreateOrUpdatePage,
CreateOrUpdateType,
},
InCommunity, InCommunity,
}, },
SendActivity, SendActivity,
@ -214,14 +210,6 @@ impl SendActivity for FeaturePost {
context: &Data<LemmyContext>, context: &Data<LemmyContext>,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let local_user_view = local_user_view_from_jwt(&request.auth, context).await?; let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
// Deprecated, for backwards compatibility with 0.17
CreateOrUpdatePage::send(
&response.post_view.post,
local_user_view.person.id,
CreateOrUpdateType::Update,
context,
)
.await?;
let community = Community::read(context.pool(), response.post_view.community.id) let community = Community::read(context.pool(), response.post_view.community.id)
.await? .await?
.into(); .into();

View file

@ -10,11 +10,7 @@ use crate::{
activity_lists::AnnouncableActivities, activity_lists::AnnouncableActivities,
insert_activity, insert_activity,
protocol::{ protocol::{
activities::{ activities::community::lock_page::{LockPage, LockType, UndoLockPage},
community::lock_page::{LockPage, LockType, UndoLockPage},
create_or_update::page::CreateOrUpdatePage,
CreateOrUpdateType,
},
InCommunity, InCommunity,
}, },
SendActivity, SendActivity,
@ -116,14 +112,6 @@ impl SendActivity for LockPost {
context: &Data<LemmyContext>, context: &Data<LemmyContext>,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let local_user_view = local_user_view_from_jwt(&request.auth, context).await?; let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
// For backwards compat with 0.17
CreateOrUpdatePage::send(
&response.post_view.post,
local_user_view.person.id,
CreateOrUpdateType::Update,
context,
)
.await?;
let id = generate_activity_id( let id = generate_activity_id(
LockType::Lock, LockType::Lock,
&context.settings().get_protocol_and_hostname(), &context.settings().get_protocol_and_hostname(),

View file

@ -152,16 +152,13 @@ impl ActivityHandler for CreateOrUpdatePage {
CreateOrUpdateType::Create => { CreateOrUpdateType::Create => {
verify_domains_match(self.actor.inner(), self.object.id.inner())?; verify_domains_match(self.actor.inner(), self.object.id.inner())?;
verify_urls_match(self.actor.inner(), self.object.creator()?.inner())?; verify_urls_match(self.actor.inner(), self.object.creator()?.inner())?;
// Check that the post isnt locked or stickied, as that isnt possible for newly created posts. // Check that the post isnt locked, as that isnt possible for newly created posts.
// However, when fetching a remote post we generate a new create activity with the current // However, when fetching a remote post we generate a new create activity with the current
// locked/stickied value, so this check may fail. So only check if its a local community, // locked value, so this check may fail. So only check if its a local community,
// because then we will definitely receive all create and update activities separately. // because then we will definitely receive all create and update activities separately.
let is_featured_or_locked = let is_locked = self.object.comments_enabled == Some(false);
self.object.stickied == Some(true) || self.object.comments_enabled == Some(false); if community.local && is_locked {
if community.local && is_featured_or_locked { return Err(LemmyError::from_message("New post cannot be locked"));
return Err(LemmyError::from_message(
"New post cannot be stickied or locked",
));
} }
} }
CreateOrUpdateType::Update => { CreateOrUpdateType::Update => {

View file

@ -96,7 +96,6 @@ impl Object for ApubCommunity {
icon: self.icon.clone().map(ImageObject::new), icon: self.icon.clone().map(ImageObject::new),
image: self.banner.clone().map(ImageObject::new), image: self.banner.clone().map(ImageObject::new),
sensitive: Some(self.nsfw), sensitive: Some(self.nsfw),
moderators: Some(generate_moderators_url(&self.actor_id)?.into()),
featured: Some(generate_featured_url(&self.actor_id)?.into()), featured: Some(generate_featured_url(&self.actor_id)?.into()),
inbox: self.inbox_url.clone().into(), inbox: self.inbox_url.clone().into(),
outbox: generate_outbox_url(&self.actor_id)?.into(), outbox: generate_outbox_url(&self.actor_id)?.into(),
@ -148,7 +147,7 @@ impl Object for ApubCommunity {
.map_err(|e| debug!("{}", e)) .map_err(|e| debug!("{}", e))
.ok(); .ok();
if let Some(moderators) = group.attributed_to.or(group.moderators) { if let Some(moderators) = group.attributed_to {
moderators moderators
.dereference(&community, context) .dereference(&community, context)
.await .await
@ -231,7 +230,6 @@ pub(crate) mod tests {
let context2 = context.reset_request_count(); let context2 = context.reset_request_count();
let mut json: Group = file_to_json_object("assets/lemmy/objects/group.json").unwrap(); let mut json: Group = file_to_json_object("assets/lemmy/objects/group.json").unwrap();
// change these links so they dont fetch over the network // change these links so they dont fetch over the network
json.moderators = None;
json.attributed_to = None; json.attributed_to = None;
json.outbox = json.outbox =
CollectionId::parse("https://enterprise.lemmy.ml/c/tenforward/not_outbox").unwrap(); CollectionId::parse("https://enterprise.lemmy.ml/c/tenforward/not_outbox").unwrap();

View file

@ -32,7 +32,7 @@ use lemmy_db_schema::{
source::{ source::{
community::Community, community::Community,
local_site::LocalSite, local_site::LocalSite,
moderator::{ModFeaturePost, ModFeaturePostForm, ModLockPost, ModLockPostForm}, moderator::{ModLockPost, ModLockPostForm},
person::Person, person::Person,
post::{Post, PostInsertForm, PostUpdateForm}, post::{Post, PostInsertForm, PostUpdateForm},
}, },
@ -121,7 +121,6 @@ impl Object for ApubPost {
image: self.thumbnail_url.clone().map(ImageObject::new), image: self.thumbnail_url.clone().map(ImageObject::new),
comments_enabled: Some(!self.locked), comments_enabled: Some(!self.locked),
sensitive: Some(self.nsfw), sensitive: Some(self.nsfw),
stickied: Some(self.featured_community),
language, language,
published: Some(convert_datetime(self.published)), published: Some(convert_datetime(self.published)),
updated: self.updated.map(convert_datetime), updated: self.updated.map(convert_datetime),
@ -236,7 +235,7 @@ impl Object for ApubPost {
ap_id: Some(page.id.clone().into()), ap_id: Some(page.id.clone().into()),
local: Some(false), local: Some(false),
language_id, language_id,
featured_community: page.stickied, featured_community: None,
featured_local: None, featured_local: None,
} }
} else { } else {
@ -247,23 +246,13 @@ impl Object for ApubPost {
.community_id(community.id) .community_id(community.id)
.ap_id(Some(page.id.clone().into())) .ap_id(Some(page.id.clone().into()))
.locked(page.comments_enabled.map(|e| !e)) .locked(page.comments_enabled.map(|e| !e))
.featured_community(page.stickied)
.updated(page.updated.map(|u| u.naive_local())) .updated(page.updated.map(|u| u.naive_local()))
.build() .build()
}; };
let post = Post::create(context.pool(), &form).await?; let post = Post::create(context.pool(), &form).await?;
// write mod log entries for feature/lock // write mod log entry for lock
if Page::is_featured_changed(&old_post, &page.stickied) {
let form = ModFeaturePostForm {
mod_person_id: creator.id,
post_id: post.id,
featured: post.featured_community,
is_featured_community: true,
};
ModFeaturePost::create(context.pool(), &form).await?;
}
if Page::is_locked_changed(&old_post, &page.comments_enabled) { if Page::is_locked_changed(&old_post, &page.comments_enabled) {
let form = ModLockPostForm { let form = ModLockPostForm {
mod_person_id: creator.id, mod_person_id: creator.id,
@ -309,7 +298,7 @@ mod tests {
assert!(post.body.is_some()); assert!(post.body.is_some());
assert_eq!(post.body.as_ref().unwrap().len(), 45); assert_eq!(post.body.as_ref().unwrap().len(), 45);
assert!(!post.locked); assert!(!post.locked);
assert!(post.featured_community); assert!(!post.featured_community);
assert_eq!(context.request_count(), 0); assert_eq!(context.request_count(), 0);
Post::delete(context.pool(), post.id).await.unwrap(); Post::delete(context.pool(), post.id).await.unwrap();

View file

@ -61,8 +61,6 @@ pub struct Group {
pub(crate) image: Option<ImageObject>, pub(crate) image: Option<ImageObject>,
// lemmy extension // lemmy extension
pub(crate) sensitive: Option<bool>, pub(crate) sensitive: Option<bool>,
// deprecated, use attributed_to instead
pub(crate) moderators: Option<CollectionId<ApubCommunityModerators>>,
#[serde(deserialize_with = "deserialize_skip_error", default)] #[serde(deserialize_with = "deserialize_skip_error", default)]
pub(crate) attributed_to: Option<CollectionId<ApubCommunityModerators>>, pub(crate) attributed_to: Option<CollectionId<ApubCommunityModerators>>,
// lemmy extension // lemmy extension
@ -122,7 +120,7 @@ impl Group {
followers_url: Some(self.followers.into()), followers_url: Some(self.followers.into()),
inbox_url: Some(self.inbox.into()), inbox_url: Some(self.inbox.into()),
shared_inbox_url: self.endpoints.map(|e| e.shared_inbox.into()), shared_inbox_url: self.endpoints.map(|e| e.shared_inbox.into()),
moderators_url: self.moderators.map(Into::into), moderators_url: self.attributed_to.map(Into::into),
posting_restricted_to_mods: self.posting_restricted_to_mods, posting_restricted_to_mods: self.posting_restricted_to_mods,
instance_id, instance_id,
featured_url: self.featured.map(Into::into), featured_url: self.featured.map(Into::into),
@ -153,7 +151,7 @@ impl Group {
followers_url: Some(self.followers.into()), followers_url: Some(self.followers.into()),
inbox_url: Some(self.inbox.into()), inbox_url: Some(self.inbox.into()),
shared_inbox_url: Some(self.endpoints.map(|e| e.shared_inbox.into())), shared_inbox_url: Some(self.endpoints.map(|e| e.shared_inbox.into())),
moderators_url: self.moderators.map(Into::into), moderators_url: self.attributed_to.map(Into::into),
posting_restricted_to_mods: self.posting_restricted_to_mods, posting_restricted_to_mods: self.posting_restricted_to_mods,
featured_url: self.featured.map(Into::into), featured_url: self.featured.map(Into::into),
} }

View file

@ -63,8 +63,6 @@ pub struct Page {
pub(crate) image: Option<ImageObject>, pub(crate) image: Option<ImageObject>,
pub(crate) comments_enabled: Option<bool>, pub(crate) comments_enabled: Option<bool>,
pub(crate) sensitive: Option<bool>, pub(crate) sensitive: Option<bool>,
/// Deprecated, for compatibility with Lemmy 0.17
pub(crate) stickied: Option<bool>,
pub(crate) published: Option<DateTime<FixedOffset>>, pub(crate) published: Option<DateTime<FixedOffset>>,
pub(crate) updated: Option<DateTime<FixedOffset>>, pub(crate) updated: Option<DateTime<FixedOffset>>,
pub(crate) language: Option<LanguageTag>, pub(crate) language: Option<LanguageTag>,
@ -131,32 +129,16 @@ pub(crate) struct AttributedToPeertube {
} }
impl Page { impl Page {
/// Only mods can change the post's stickied/locked status. So if either of these is changed from /// Only mods can change the post's locked status. So if it is changed from the default value,
/// the current value, it is a mod action and needs to be verified as such. /// it is a mod action and needs to be verified as such.
/// ///
/// Both stickied and locked need to be false on a newly created post (verified in [[CreatePost]]. /// Locked needs to be false on a newly created post (verified in [[CreatePost]].
pub(crate) async fn is_mod_action( pub(crate) async fn is_mod_action(
&self, &self,
context: &Data<LemmyContext>, context: &Data<LemmyContext>,
) -> Result<bool, LemmyError> { ) -> Result<bool, LemmyError> {
let old_post = self.id.clone().dereference_local(context).await; let old_post = self.id.clone().dereference_local(context).await;
Ok(Page::is_locked_changed(&old_post, &self.comments_enabled))
let featured_changed = Page::is_featured_changed(&old_post, &self.stickied);
let locked_changed = Page::is_locked_changed(&old_post, &self.comments_enabled);
Ok(featured_changed || locked_changed)
}
pub(crate) fn is_featured_changed<E>(
old_post: &Result<ApubPost, E>,
new_featured_community: &Option<bool>,
) -> bool {
if let Some(new_featured_community) = new_featured_community {
if let Ok(old_post) = old_post {
return new_featured_community != &old_post.featured_community;
}
}
false
} }
pub(crate) fn is_locked_changed<E>( pub(crate) fn is_locked_changed<E>(

View file

@ -337,7 +337,6 @@ diesel::table! {
slur_filter_regex -> Nullable<Text>, slur_filter_regex -> Nullable<Text>,
actor_name_max_length -> Int4, actor_name_max_length -> Int4,
federation_enabled -> Bool, federation_enabled -> Bool,
federation_debug -> Bool,
federation_worker_count -> Int4, federation_worker_count -> Int4,
captcha_enabled -> Bool, captcha_enabled -> Bool,
#[max_length = 255] #[max_length = 255]

View file

@ -50,7 +50,6 @@ pub struct LocalSite {
pub actor_name_max_length: i32, pub actor_name_max_length: i32,
/// Whether federation is enabled. /// Whether federation is enabled.
pub federation_enabled: bool, pub federation_enabled: bool,
pub federation_debug: bool,
/// The number of concurrent federation http workers. /// The number of concurrent federation http workers.
pub federation_worker_count: i32, pub federation_worker_count: i32,
/// Whether captcha is enabled. /// Whether captcha is enabled.
@ -86,7 +85,6 @@ pub struct LocalSiteInsertForm {
pub slur_filter_regex: Option<String>, pub slur_filter_regex: Option<String>,
pub actor_name_max_length: Option<i32>, pub actor_name_max_length: Option<i32>,
pub federation_enabled: Option<bool>, pub federation_enabled: Option<bool>,
pub federation_debug: Option<bool>,
pub federation_worker_count: Option<i32>, pub federation_worker_count: Option<i32>,
pub captcha_enabled: Option<bool>, pub captcha_enabled: Option<bool>,
pub captcha_difficulty: Option<String>, pub captcha_difficulty: Option<String>,
@ -114,7 +112,6 @@ pub struct LocalSiteUpdateForm {
pub slur_filter_regex: Option<Option<String>>, pub slur_filter_regex: Option<Option<String>>,
pub actor_name_max_length: Option<i32>, pub actor_name_max_length: Option<i32>,
pub federation_enabled: Option<bool>, pub federation_enabled: Option<bool>,
pub federation_debug: Option<bool>,
pub federation_worker_count: Option<i32>, pub federation_worker_count: Option<i32>,
pub captcha_enabled: Option<bool>, pub captcha_enabled: Option<bool>,
pub captcha_difficulty: Option<String>, pub captcha_difficulty: Option<String>,

View file

@ -0,0 +1 @@
alter table local_site add column federation_debug int default 0;

View file

@ -0,0 +1 @@
alter table local_site drop column federation_debug;