fix(application): gate federation broadcast on Public/Unlisted visibility only
This commit is contained in:
@@ -2,6 +2,7 @@ use std::sync::Arc;
|
||||
use domain::{
|
||||
errors::DomainError,
|
||||
events::DomainEvent,
|
||||
models::thought::Visibility,
|
||||
ports::{OutboundFederationPort, ThoughtRepository, UserRepository},
|
||||
};
|
||||
|
||||
@@ -17,7 +18,7 @@ impl FederationEventService {
|
||||
match event {
|
||||
DomainEvent::ThoughtCreated { thought_id, user_id, .. } => {
|
||||
let thought = match self.thoughts.find_by_id(thought_id).await? {
|
||||
Some(t) if t.local => t,
|
||||
Some(t) if t.local && matches!(t.visibility, Visibility::Public | Visibility::Unlisted) => t,
|
||||
_ => return Ok(()),
|
||||
};
|
||||
let user = match self.users.find_by_id(user_id).await? {
|
||||
@@ -36,7 +37,7 @@ impl FederationEventService {
|
||||
|
||||
DomainEvent::ThoughtUpdated { thought_id, user_id } => {
|
||||
let thought = match self.thoughts.find_by_id(thought_id).await? {
|
||||
Some(t) if t.local => t,
|
||||
Some(t) if t.local && matches!(t.visibility, Visibility::Public | Visibility::Unlisted) => t,
|
||||
_ => return Ok(()),
|
||||
};
|
||||
let user = match self.users.find_by_id(user_id).await? {
|
||||
@@ -265,6 +266,56 @@ mod tests {
|
||||
assert_eq!(announced[0], "https://mastodon.social/users/bob/statuses/123");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn direct_thought_created_does_not_broadcast() {
|
||||
let store = TestStore::default();
|
||||
let alice = alice();
|
||||
let thought = Thought::new_local(
|
||||
ThoughtId::new(), alice.id.clone(),
|
||||
Content::new_local("private").unwrap(),
|
||||
None, Visibility::Direct, None, false,
|
||||
);
|
||||
store.users.lock().unwrap().push(alice.clone());
|
||||
store.thoughts.lock().unwrap().push(thought.clone());
|
||||
|
||||
let spy = Arc::new(SpyPort::default());
|
||||
svc(&store, spy.clone())
|
||||
.process(&DomainEvent::ThoughtCreated {
|
||||
thought_id: thought.id.clone(),
|
||||
user_id: alice.id.clone(),
|
||||
in_reply_to_id: None,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(spy.created.lock().unwrap().is_empty());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn followers_only_thought_does_not_broadcast_publicly() {
|
||||
let store = TestStore::default();
|
||||
let alice = alice();
|
||||
let thought = Thought::new_local(
|
||||
ThoughtId::new(), alice.id.clone(),
|
||||
Content::new_local("for followers").unwrap(),
|
||||
None, Visibility::Followers, None, false,
|
||||
);
|
||||
store.users.lock().unwrap().push(alice.clone());
|
||||
store.thoughts.lock().unwrap().push(thought.clone());
|
||||
|
||||
let spy = Arc::new(SpyPort::default());
|
||||
svc(&store, spy.clone())
|
||||
.process(&DomainEvent::ThoughtCreated {
|
||||
thought_id: thought.id.clone(),
|
||||
user_id: alice.id.clone(),
|
||||
in_reply_to_id: None,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(spy.created.lock().unwrap().is_empty());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn unrelated_events_are_noop() {
|
||||
let store = TestStore::default();
|
||||
|
||||
Reference in New Issue
Block a user