diff --git a/src/activitypub/builders/create_note.rs b/src/activitypub/builders/create_note.rs index 39c91f3..53c3279 100644 --- a/src/activitypub/builders/create_note.rs +++ b/src/activitypub/builders/create_note.rs @@ -20,7 +20,6 @@ use crate::errors::DatabaseError; use crate::frontend::get_tag_page_url; use crate::models::posts::queries::get_post_author; use crate::models::posts::types::{Post, Visibility}; -use crate::models::profiles::types::DbActorProfile; use crate::models::relationships::queries::{get_followers, get_subscribers}; use crate::models::users::types::User; use crate::utils::files::get_file_url; @@ -59,7 +58,6 @@ pub fn build_note( instance_host: &str, instance_url: &str, post: &Post, - subscribers: Vec, ) -> Note { let object_id = local_object_id(instance_url, &post.id); let actor_id = local_actor_id(instance_url, &post.author.username); @@ -95,13 +93,7 @@ pub fn build_note( }; let mut tags = vec![]; - let mut mentions = post.mentions.clone(); - if post.visibility == Visibility::Subscribers { - // Mention all subscribers - // (for recipients that don't support subscribers-only posts) - mentions.extend(subscribers); - }; - for profile in mentions { + for profile in &post.mentions { let tag_name = format!("@{}", profile.actor_address(instance_host)); let actor_id = profile.actor_id(instance_url); if !primary_audience.contains(&actor_id) { @@ -154,9 +146,8 @@ pub fn build_create_note( instance_host: &str, instance_url: &str, post: &Post, - subscribers: Vec, ) -> Activity { - let object = build_note(instance_host, instance_url, post, subscribers); + let object = build_note(instance_host, instance_url, post); let primary_audience = object.to.clone(); let secondary_audience = object.cc.clone(); let activity_id = format!("{}/create", object.id); @@ -212,16 +203,10 @@ pub async fn prepare_create_note( post: &Post, ) -> Result, DatabaseError> { assert_eq!(author.id, post.author.id); - let subscribers = if post.visibility == Visibility::Subscribers { - get_subscribers(db_client, &author.id).await? - } else { - vec![] - }; let activity = build_create_note( &instance.host(), &instance.url(), post, - subscribers, ); let recipients = get_note_recipients(db_client, author, post).await?; Ok(OutgoingActivity { @@ -235,6 +220,7 @@ pub async fn prepare_create_note( #[cfg(test)] mod tests { use serde_json::json; + use crate::models::profiles::types::DbActorProfile; use super::*; const INSTANCE_HOST: &str = "example.com"; @@ -247,7 +233,7 @@ mod tests { ..Default::default() }; let post = Post { author, ..Default::default() }; - let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post, vec![]); + let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post); assert_eq!( note.id, @@ -272,7 +258,7 @@ mod tests { visibility: Visibility::Followers, ..Default::default() }; - let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post, vec![]); + let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post); assert_eq!(note.to, vec![ local_actor_followers(INSTANCE_URL, &post.author.username), @@ -282,10 +268,6 @@ mod tests { #[test] fn test_build_note_subscribers_only() { - let post = Post { - visibility: Visibility::Subscribers, - ..Default::default() - }; let subscriber_id = "https://test.com/users/3"; let subscriber = DbActorProfile { username: "subscriber".to_string(), @@ -296,7 +278,12 @@ mod tests { actor_id: Some(subscriber_id.to_string()), ..Default::default() }; - let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post, vec![subscriber]); + let post = Post { + visibility: Visibility::Subscribers, + mentions: vec![subscriber], + ..Default::default() + }; + let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post); assert_eq!(note.to, vec![ local_actor_subscribers(INSTANCE_URL, &post.author.username), @@ -322,7 +309,7 @@ mod tests { mentions: vec![mentioned], ..Default::default() }; - let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post, vec![]); + let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post); assert_eq!(note.to, vec![mentioned_id]); assert_eq!(note.cc.is_empty(), true); @@ -336,7 +323,7 @@ mod tests { in_reply_to: Some(Box::new(parent.clone())), ..Default::default() }; - let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post, vec![]); + let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post); assert_eq!( note.in_reply_to.unwrap(), @@ -374,7 +361,7 @@ mod tests { mentions: vec![parent_author], ..Default::default() }; - let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post, vec![]); + let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post); assert_eq!( note.in_reply_to.unwrap(), @@ -399,7 +386,6 @@ mod tests { INSTANCE_HOST, INSTANCE_URL, &post, - vec![], ); assert_eq!( diff --git a/src/activitypub/builders/delete_note.rs b/src/activitypub/builders/delete_note.rs index 3b6928a..99aa98e 100644 --- a/src/activitypub/builders/delete_note.rs +++ b/src/activitypub/builders/delete_note.rs @@ -7,9 +7,7 @@ use crate::activitypub::deliverer::OutgoingActivity; use crate::activitypub::vocabulary::{DELETE, NOTE, TOMBSTONE}; use crate::config::Instance; use crate::errors::DatabaseError; -use crate::models::posts::types::{Post, Visibility}; -use crate::models::profiles::types::DbActorProfile; -use crate::models::relationships::queries::get_subscribers; +use crate::models::posts::types::Post; use crate::models::users::types::User; use super::create_note::{ build_note, @@ -21,7 +19,6 @@ fn build_delete_note( instance_host: &str, instance_url: &str, post: &Post, - subscribers: Vec, ) -> Activity { let object_id = post.get_object_id(instance_url); let object = Object { @@ -36,7 +33,6 @@ fn build_delete_note( instance_host, instance_url, post, - subscribers, ); let activity = create_activity( instance_url, @@ -57,16 +53,10 @@ pub async fn prepare_delete_note( post: &Post, ) -> Result, DatabaseError> { assert_eq!(author.id, post.author.id); - let subscribers = if post.visibility == Visibility::Subscribers { - get_subscribers(db_client, &author.id).await? - } else { - vec![] - }; let activity = build_delete_note( &instance.host(), &instance.url(), post, - subscribers, ); let recipients = get_note_recipients(db_client, author, post).await?; Ok(OutgoingActivity { @@ -84,6 +74,7 @@ mod tests { constants::AP_PUBLIC, identifiers::local_actor_followers, }; + use crate::models::profiles::types::DbActorProfile; use super::*; const INSTANCE_HOST: &str = "example.com"; @@ -100,7 +91,6 @@ mod tests { INSTANCE_HOST, INSTANCE_URL, &post, - vec![], ); assert_eq!( diff --git a/src/activitypub/views.rs b/src/activitypub/views.rs index 4d36616..8dc6bb9 100644 --- a/src/activitypub/views.rs +++ b/src/activitypub/views.rs @@ -146,7 +146,6 @@ async fn outbox( &instance.host(), &instance.url(), post, - vec![], // subscribers-only posts are not included ); Some(activity) }).collect(); @@ -300,7 +299,6 @@ pub async fn object_view( &config.instance().host(), &config.instance().url(), &post, - vec![], // subscribers-only posts are not accessible ); let response = HttpResponse::Ok() .content_type(ACTIVITY_CONTENT_TYPE) diff --git a/src/mastodon_api/statuses/views.rs b/src/mastodon_api/statuses/views.rs index 7f7e6d5..b716020 100644 --- a/src/mastodon_api/statuses/views.rs +++ b/src/mastodon_api/statuses/views.rs @@ -38,6 +38,7 @@ use crate::models::reactions::queries::{ create_reaction, delete_reaction, }; +use crate::models::relationships::queries::get_subscribers; use crate::utils::currencies::Currency; use super::helpers::{ build_status, @@ -71,6 +72,15 @@ async fn create_status( ); post_data.mentions.extend(mention_map.values() .map(|profile| profile.id)); + if post_data.visibility == Visibility::Subscribers { + // Mention all subscribers. + // This makes post accessible only to active subscribers + // and is required for sending activities to subscribers + // on other instances. + let subscribers = get_subscribers(db_client, ¤t_user.id).await? + .into_iter().map(|profile| profile.id); + post_data.mentions.extend(subscribers); + }; post_data.mentions.sort(); post_data.mentions.dedup(); // Hashtags diff --git a/src/models/posts/queries.rs b/src/models/posts/queries.rs index 99e2a16..65b1190 100644 --- a/src/models/posts/queries.rs +++ b/src/models/posts/queries.rs @@ -263,6 +263,7 @@ fn build_visibility_filter() -> String { AND target_id = post.author_id AND relationship_type = {relationship_follow} ) + -- TODO: remove and rely on mentions instead OR post.visibility = {visibility_subscribers} AND EXISTS ( SELECT 1 FROM relationship WHERE