Compare commits
2 Commits
9355f20616
...
902d38cc76
| Author | SHA1 | Date | |
|---|---|---|---|
| 902d38cc76 | |||
| f461f633b3 |
@@ -1,5 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [0.4.2] — 2026-07-10
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
- `FederationEvent::OutboundFollowAccepted { local_user_id, remote_actor_url, outbox_url }` — emitted when a remote actor accepts our outbound follow request. Consumers should call `import_remote_outbox(outbox_url, actor_url)` to backfill the remote user's content. Without this event, outbound follow acceptance was silent and consumers had no hook to trigger backfill.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## [0.4.1] — 2026-06-30
|
## [0.4.1] — 2026-06-30
|
||||||
|
|
||||||
### Bug fixes
|
### Bug fixes
|
||||||
|
|||||||
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -1368,7 +1368,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "k-ap"
|
name = "k-ap"
|
||||||
version = "0.4.0"
|
version = "0.4.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"activitypub_federation",
|
"activitypub_federation",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "k-ap"
|
name = "k-ap"
|
||||||
version = "0.4.1"
|
version = "0.4.2"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
description = "Generic ActivityPub protocol layer"
|
description = "Generic ActivityPub protocol layer"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|||||||
@@ -49,14 +49,28 @@ impl Activity for AcceptActivity {
|
|||||||
}
|
}
|
||||||
let local_user_id = crate::urls::extract_user_id_from_url(self.object.actor.inner())
|
let local_user_id = crate::urls::extract_user_id_from_url(self.object.actor.inner())
|
||||||
.ok_or_else(|| Error::bad_request(anyhow::anyhow!("invalid actor URL in Follow")))?;
|
.ok_or_else(|| Error::bad_request(anyhow::anyhow!("invalid actor URL in Follow")))?;
|
||||||
|
let remote_actor_url = self.actor.inner().as_str().to_string();
|
||||||
data.follow_repo
|
data.follow_repo
|
||||||
.update_following_status(
|
.update_following_status(local_user_id, &remote_actor_url, FollowingStatus::Accepted)
|
||||||
local_user_id,
|
|
||||||
self.actor.inner().as_str(),
|
|
||||||
FollowingStatus::Accepted,
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
tracing::info!(remote_actor = %self.actor.inner(), "follow accepted by remote");
|
tracing::info!(remote_actor = %remote_actor_url, "follow accepted by remote");
|
||||||
|
|
||||||
|
if let Some(publisher) = &data.event_publisher {
|
||||||
|
let outbox_url = data
|
||||||
|
.actor_repo
|
||||||
|
.get_remote_actor(&remote_actor_url)
|
||||||
|
.await
|
||||||
|
.ok()
|
||||||
|
.flatten()
|
||||||
|
.and_then(|a| a.outbox_url);
|
||||||
|
let _ = publisher
|
||||||
|
.publish(crate::data::FederationEvent::OutboundFollowAccepted {
|
||||||
|
local_user_id,
|
||||||
|
remote_actor_url,
|
||||||
|
outbox_url,
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,11 +119,11 @@ impl ActorUrls {
|
|||||||
fn build(base_url: &str, user_id: uuid::Uuid) -> Self {
|
fn build(base_url: &str, user_id: uuid::Uuid) -> Self {
|
||||||
let ap_id = crate::urls::actor_url(base_url, user_id);
|
let ap_id = crate::urls::actor_url(base_url, user_id);
|
||||||
Self {
|
Self {
|
||||||
inbox_url: Url::parse(&format!("{}/inbox", &ap_id)).expect("valid url"),
|
inbox_url: Url::parse(&format!("{}/inbox", ap_id)).expect("valid url"),
|
||||||
shared_inbox_url: Url::parse(&format!("{}/inbox", base_url)).ok(),
|
shared_inbox_url: Url::parse(&format!("{}/inbox", base_url)).ok(),
|
||||||
outbox_url: Url::parse(&format!("{}/outbox", &ap_id)).expect("valid url"),
|
outbox_url: Url::parse(&format!("{}/outbox", ap_id)).expect("valid url"),
|
||||||
followers_url: Url::parse(&format!("{}/followers", &ap_id)).expect("valid url"),
|
followers_url: Url::parse(&format!("{}/followers", ap_id)).expect("valid url"),
|
||||||
following_url: Url::parse(&format!("{}/following", &ap_id)).expect("valid url"),
|
following_url: Url::parse(&format!("{}/following", ap_id)).expect("valid url"),
|
||||||
ap_id,
|
ap_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -285,7 +285,7 @@ impl Object for DbActor {
|
|||||||
|
|
||||||
async fn into_json(self, data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
async fn into_json(self, data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
||||||
let public_key = PublicKey {
|
let public_key = PublicKey {
|
||||||
id: format!("{}#main-key", &self.ap_id),
|
id: format!("{}#main-key", self.ap_id),
|
||||||
owner: self.ap_id.clone(),
|
owner: self.ap_id.clone(),
|
||||||
public_key_pem: self.public_key_pem.clone(),
|
public_key_pem: self.public_key_pem.clone(),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -41,6 +41,13 @@ pub enum FederationEvent {
|
|||||||
owner_user_id: uuid::Uuid,
|
owner_user_id: uuid::Uuid,
|
||||||
follower_inbox_url: String,
|
follower_inbox_url: String,
|
||||||
},
|
},
|
||||||
|
/// A remote actor accepted our outbound follow request.
|
||||||
|
/// Call `ActivityPubService::import_remote_outbox(outbox_url, actor_url)` to backfill.
|
||||||
|
OutboundFollowAccepted {
|
||||||
|
local_user_id: uuid::Uuid,
|
||||||
|
remote_actor_url: String,
|
||||||
|
outbox_url: Option<String>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Receives typed federation events.
|
/// Receives typed federation events.
|
||||||
|
|||||||
Reference in New Issue
Block a user