From 6bd728fd50d5bbefa63f7d25184a8eb9cf943928 Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Sat, 30 May 2026 03:16:03 +0200 Subject: [PATCH] feat: replace instance actor decorator with real DB row Migrations (postgres + sqlite) insert a service actor with a well-known UUID. Removes the InstanceActorUserRepo wrapper. --- .../activitypub/src/instance_actor.rs | 57 ------------------- crates/adapters/activitypub/src/lib.rs | 15 ++--- .../migrations/0022_instance_actor.sql | 10 ++++ .../sqlite/migrations/0022_instance_actor.sql | 8 +++ 4 files changed, 26 insertions(+), 64 deletions(-) delete mode 100644 crates/adapters/activitypub/src/instance_actor.rs create mode 100644 crates/adapters/postgres/migrations/0022_instance_actor.sql create mode 100644 crates/adapters/sqlite/migrations/0022_instance_actor.sql diff --git a/crates/adapters/activitypub/src/instance_actor.rs b/crates/adapters/activitypub/src/instance_actor.rs deleted file mode 100644 index 77192f0..0000000 --- a/crates/adapters/activitypub/src/instance_actor.rs +++ /dev/null @@ -1,57 +0,0 @@ -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, - base_url: String, -} - -impl InstanceActorUserRepo { - pub fn new(inner: Arc, 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> { - 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> { - 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 { - self.inner.count_users().await - } -} diff --git a/crates/adapters/activitypub/src/lib.rs b/crates/adapters/activitypub/src/lib.rs index af65e9e..cd2c8d1 100644 --- a/crates/adapters/activitypub/src/lib.rs +++ b/crates/adapters/activitypub/src/lib.rs @@ -1,7 +1,6 @@ pub mod composite_handler; pub mod event_handler; pub mod federation_event_bridge; -pub mod instance_actor; pub mod objects; pub mod port; pub mod remote_review_repository; @@ -10,6 +9,9 @@ pub(crate) mod urls; pub mod user_adapter; pub mod watchlist_handler; +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]); + // Re-export the generic base types that callers need pub use k_ap::{ ActivityPubService, ActivityRepository, ActorRepository, ApContentReader, ApFederationConfig, @@ -97,18 +99,17 @@ pub async fn wire(deps: ActivityPubDeps) -> anyhow::Result { federation_event_bridge::FederationEventBridge::new(event_publisher), ); - let user_repo = std::sync::Arc::new(instance_actor::InstanceActorUserRepo::new( - std::sync::Arc::new(DomainUserRepoAdapter::new(user_repo, base_url.clone())), - base_url.clone(), - )); let concrete = std::sync::Arc::new( ActivityPubService::builder(base_url.clone()) .activity_repo(activity_repo) .follow_repo(follow_repo) .actor_repo(actor_repo) .blocklist_repo(blocklist_repo) - .user_repo(user_repo) - .signed_fetch_actor_id(instance_actor::INSTANCE_ACTOR_ID) + .user_repo(std::sync::Arc::new(DomainUserRepoAdapter::new( + user_repo, + base_url.clone(), + ))) + .signed_fetch_actor_id(INSTANCE_ACTOR_ID) .content_reader(composite.clone() as std::sync::Arc) .object_handler(composite as std::sync::Arc) .event_publisher(fed_event_bridge) diff --git a/crates/adapters/postgres/migrations/0022_instance_actor.sql b/crates/adapters/postgres/migrations/0022_instance_actor.sql new file mode 100644 index 0000000..35774ff --- /dev/null +++ b/crates/adapters/postgres/migrations/0022_instance_actor.sql @@ -0,0 +1,10 @@ +INSERT INTO users (id, username, email, password_hash, created_at, role) +VALUES ( + '00000000-0000-4000-8000-000000000000', + 'instance', + 'noreply@instance.invalid', + '!service-actor-no-login', + NOW(), + 'standard' +) +ON CONFLICT (id) DO NOTHING; diff --git a/crates/adapters/sqlite/migrations/0022_instance_actor.sql b/crates/adapters/sqlite/migrations/0022_instance_actor.sql new file mode 100644 index 0000000..4219434 --- /dev/null +++ b/crates/adapters/sqlite/migrations/0022_instance_actor.sql @@ -0,0 +1,8 @@ +INSERT OR IGNORE INTO users (id, email, password_hash, created_at, username) +VALUES ( + '00000000-0000-4000-8000-000000000000', + 'noreply@instance.invalid', + '!service-actor-no-login', + datetime('now'), + 'instance' +);