fix(activitypub-base): deterministic announce IDs so Undo(Announce) can reference original activity
This commit is contained in:
@@ -175,8 +175,19 @@ impl ActivityPubService {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deterministic ID so Undo(Announce) can reference this same activity.
|
||||||
|
let announce_id = url::Url::parse(&format!(
|
||||||
|
"{}/activities/announce/{}",
|
||||||
|
self.base_url,
|
||||||
|
uuid::Uuid::new_v5(
|
||||||
|
&uuid::Uuid::NAMESPACE_URL,
|
||||||
|
format!("{}/{}", local_user_id, object_ap_id).as_bytes(),
|
||||||
|
)
|
||||||
|
))
|
||||||
|
.map_err(|e| anyhow::anyhow!("{e}"))?;
|
||||||
|
|
||||||
let announce = crate::activities::AnnounceActivity {
|
let announce = crate::activities::AnnounceActivity {
|
||||||
id: crate::urls::activity_url(&self.base_url).map_err(|e| anyhow::anyhow!("{e}"))?,
|
id: announce_id,
|
||||||
kind: Default::default(),
|
kind: Default::default(),
|
||||||
actor: activitypub_federation::fetch::object_id::ObjectId::from(local_actor.ap_id.clone()),
|
actor: activitypub_federation::fetch::object_id::ObjectId::from(local_actor.ap_id.clone()),
|
||||||
object: object_ap_id,
|
object: object_ap_id,
|
||||||
@@ -235,6 +246,17 @@ impl ActivityPubService {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reconstruct the same deterministic announce ID used when the boost was sent.
|
||||||
|
let announce_id = url::Url::parse(&format!(
|
||||||
|
"{}/activities/announce/{}",
|
||||||
|
self.base_url,
|
||||||
|
uuid::Uuid::new_v5(
|
||||||
|
&uuid::Uuid::NAMESPACE_URL,
|
||||||
|
format!("{}/{}", local_user_id, object_ap_id).as_bytes(),
|
||||||
|
)
|
||||||
|
))
|
||||||
|
.map_err(|e| anyhow::anyhow!("{e}"))?;
|
||||||
|
|
||||||
let undo_id = crate::urls::activity_url(&self.base_url).map_err(|e| anyhow::anyhow!("{e}"))?;
|
let undo_id = crate::urls::activity_url(&self.base_url).map_err(|e| anyhow::anyhow!("{e}"))?;
|
||||||
let undo = crate::activities::UndoActivity {
|
let undo = crate::activities::UndoActivity {
|
||||||
id: undo_id,
|
id: undo_id,
|
||||||
@@ -242,6 +264,7 @@ impl ActivityPubService {
|
|||||||
actor: activitypub_federation::fetch::object_id::ObjectId::from(local_actor.ap_id.clone()),
|
actor: activitypub_federation::fetch::object_id::ObjectId::from(local_actor.ap_id.clone()),
|
||||||
object: serde_json::json!({
|
object: serde_json::json!({
|
||||||
"type": "Announce",
|
"type": "Announce",
|
||||||
|
"id": announce_id.to_string(),
|
||||||
"actor": local_actor.ap_id.to_string(),
|
"actor": local_actor.ap_id.to_string(),
|
||||||
"object": object_ap_id.to_string(),
|
"object": object_ap_id.to_string(),
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -414,6 +414,21 @@ mod tests {
|
|||||||
assert_eq!(undo_announced[0], "https://mastodon.social/users/bob/statuses/456");
|
assert_eq!(undo_announced[0], "https://mastodon.social/users/bob/statuses/456");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn boost_removed_does_not_broadcast_if_thought_missing() {
|
||||||
|
let store = TestStore::default();
|
||||||
|
let alice = alice();
|
||||||
|
let spy = Arc::new(SpyPort::default());
|
||||||
|
svc(&store, spy.clone())
|
||||||
|
.process(&DomainEvent::BoostRemoved {
|
||||||
|
user_id: alice.id.clone(),
|
||||||
|
thought_id: ThoughtId::new(), // doesn't exist in store
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert!(spy.undo_announced.lock().unwrap().is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn thought_updated_does_not_broadcast_if_user_missing() {
|
async fn thought_updated_does_not_broadcast_if_user_missing() {
|
||||||
let store = TestStore::default();
|
let store = TestStore::default();
|
||||||
|
|||||||
Reference in New Issue
Block a user