feat: add instance actor for signed fetch (Secure Mode support)
This commit is contained in:
57
crates/adapters/activitypub/src/instance_actor.rs
Normal file
57
crates/adapters/activitypub/src/instance_actor.rs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use k_ap::{ApActorType, ApUser, ApUserRepository};
|
||||||
|
|
||||||
|
pub const INSTANCE_ACTOR_ID: uuid::Uuid =
|
||||||
|
uuid::Uuid::from_bytes([0, 0, 0, 0, 0, 0, 0x40, 0, 0x80, 0, 0, 0, 0, 0, 0, 0]);
|
||||||
|
|
||||||
|
pub struct InstanceActorUserRepo {
|
||||||
|
inner: Arc<dyn ApUserRepository>,
|
||||||
|
base_url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InstanceActorUserRepo {
|
||||||
|
pub fn new(inner: Arc<dyn ApUserRepository>, base_url: String) -> Self {
|
||||||
|
Self { inner, base_url }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn instance_ap_user(base_url: &str) -> ApUser {
|
||||||
|
ApUser {
|
||||||
|
id: INSTANCE_ACTOR_ID,
|
||||||
|
username: "instance".to_string(),
|
||||||
|
display_name: None,
|
||||||
|
bio: None,
|
||||||
|
avatar_url: None,
|
||||||
|
banner_url: None,
|
||||||
|
also_known_as: vec![],
|
||||||
|
profile_url: url::Url::parse(base_url).ok(),
|
||||||
|
attachment: vec![],
|
||||||
|
manually_approves_followers: false,
|
||||||
|
discoverable: false,
|
||||||
|
actor_type: ApActorType::Service,
|
||||||
|
featured_url: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl ApUserRepository for InstanceActorUserRepo {
|
||||||
|
async fn find_by_id(&self, id: uuid::Uuid) -> anyhow::Result<Option<ApUser>> {
|
||||||
|
if id == INSTANCE_ACTOR_ID {
|
||||||
|
return Ok(Some(instance_ap_user(&self.base_url)));
|
||||||
|
}
|
||||||
|
self.inner.find_by_id(id).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_by_username(&self, username: &str) -> anyhow::Result<Option<ApUser>> {
|
||||||
|
if username == "instance" {
|
||||||
|
return Ok(Some(instance_ap_user(&self.base_url)));
|
||||||
|
}
|
||||||
|
self.inner.find_by_username(username).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn count_users(&self) -> anyhow::Result<usize> {
|
||||||
|
self.inner.count_users().await
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
pub mod handler;
|
pub mod handler;
|
||||||
|
pub mod instance_actor;
|
||||||
pub mod note;
|
pub mod note;
|
||||||
pub mod port;
|
pub mod port;
|
||||||
pub mod service;
|
pub mod service;
|
||||||
@@ -33,17 +34,22 @@ pub struct ApServiceConfig {
|
|||||||
pub async fn build_ap_service(
|
pub async fn build_ap_service(
|
||||||
cfg: ApServiceConfig,
|
cfg: ApServiceConfig,
|
||||||
) -> (Arc<ActivityPubService>, Arc<ApFederationAdapter>) {
|
) -> (Arc<ActivityPubService>, Arc<ApFederationAdapter>) {
|
||||||
|
let user_repo = Arc::new(instance_actor::InstanceActorUserRepo::new(
|
||||||
|
cfg.user_repo,
|
||||||
|
cfg.base_url.clone(),
|
||||||
|
));
|
||||||
let mut builder = ActivityPubService::builder(cfg.base_url)
|
let mut builder = ActivityPubService::builder(cfg.base_url)
|
||||||
.activity_repo(cfg.activity_repo)
|
.activity_repo(cfg.activity_repo)
|
||||||
.follow_repo(cfg.follow_repo)
|
.follow_repo(cfg.follow_repo)
|
||||||
.actor_repo(cfg.actor_repo)
|
.actor_repo(cfg.actor_repo)
|
||||||
.blocklist_repo(cfg.blocklist_repo)
|
.blocklist_repo(cfg.blocklist_repo)
|
||||||
.user_repo(cfg.user_repo)
|
.user_repo(user_repo)
|
||||||
.content_reader(cfg.ap_handler.clone())
|
.content_reader(cfg.ap_handler.clone())
|
||||||
.object_handler(cfg.ap_handler)
|
.object_handler(cfg.ap_handler)
|
||||||
.allow_registration(cfg.allow_registration)
|
.allow_registration(cfg.allow_registration)
|
||||||
.software_name("thoughts")
|
.software_name("thoughts")
|
||||||
.debug(cfg.debug);
|
.debug(cfg.debug)
|
||||||
|
.signed_fetch_actor_id(instance_actor::INSTANCE_ACTOR_ID);
|
||||||
if let Some(publisher) = cfg.event_publisher {
|
if let Some(publisher) = cfg.event_publisher {
|
||||||
builder = builder.event_publisher(publisher);
|
builder = builder.event_publisher(publisher);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,8 +136,6 @@ fn k_ap_actor_to_domain(a: k_ap::RemoteActor) -> DomainRemoteActor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: these fetches are unsigned — fails on instances with authorized-fetch (Secure Mode).
|
|
||||||
// Fix requires exposing k-ap's signed HTTP client.
|
|
||||||
async fn resolve_actor_profiles_from_urls(
|
async fn resolve_actor_profiles_from_urls(
|
||||||
urls: Vec<String>,
|
urls: Vec<String>,
|
||||||
) -> Vec<domain::models::actor_connection_summary::ActorConnectionSummary> {
|
) -> Vec<domain::models::actor_connection_summary::ActorConnectionSummary> {
|
||||||
|
|||||||
Reference in New Issue
Block a user