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::{
|
use domain::{
|
||||||
errors::DomainError,
|
errors::DomainError,
|
||||||
events::DomainEvent,
|
events::DomainEvent,
|
||||||
|
models::thought::Visibility,
|
||||||
ports::{OutboundFederationPort, ThoughtRepository, UserRepository},
|
ports::{OutboundFederationPort, ThoughtRepository, UserRepository},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ impl FederationEventService {
|
|||||||
match event {
|
match event {
|
||||||
DomainEvent::ThoughtCreated { thought_id, user_id, .. } => {
|
DomainEvent::ThoughtCreated { thought_id, user_id, .. } => {
|
||||||
let thought = match self.thoughts.find_by_id(thought_id).await? {
|
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(()),
|
_ => return Ok(()),
|
||||||
};
|
};
|
||||||
let user = match self.users.find_by_id(user_id).await? {
|
let user = match self.users.find_by_id(user_id).await? {
|
||||||
@@ -36,7 +37,7 @@ impl FederationEventService {
|
|||||||
|
|
||||||
DomainEvent::ThoughtUpdated { thought_id, user_id } => {
|
DomainEvent::ThoughtUpdated { thought_id, user_id } => {
|
||||||
let thought = match self.thoughts.find_by_id(thought_id).await? {
|
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(()),
|
_ => return Ok(()),
|
||||||
};
|
};
|
||||||
let user = match self.users.find_by_id(user_id).await? {
|
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");
|
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]
|
#[tokio::test]
|
||||||
async fn unrelated_events_are_noop() {
|
async fn unrelated_events_are_noop() {
|
||||||
let store = TestStore::default();
|
let store = TestStore::default();
|
||||||
|
|||||||
Reference in New Issue
Block a user