From 1a0acca3a0be2305fb4803dd7123a7fe300c15c1 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Fri, 8 Nov 2024 15:11:29 +0100 Subject: [PATCH] Add ghost user to be able to fetch articles in case edit author cant be fetched --- src/backend/database/user.rs | 27 ++++++++++++++++++++++++++ src/backend/federation/objects/edit.rs | 11 +++++++++-- src/backend/mod.rs | 3 +++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/backend/database/user.rs b/src/backend/database/user.rs index c493fd6..13dd02c 100644 --- a/src/backend/database/user.rs +++ b/src/backend/database/user.rs @@ -164,4 +164,31 @@ impl DbPerson { .select(instance::all_columns) .get_results(conn.deref_mut())?) } + + /// Ghost user serves as placeholder for deleted accounts + pub fn ghost(data: &Data) -> MyResult { + let username = "ghost"; + let read = DbPerson::read_from_name(username, &None, data); + if read.is_ok() { + read + } else { + let domain = &data.config.federation.domain; + let ap_id = ObjectId::parse(&format!( + "{}://{domain}/user/{username}", + http_protocol_str() + ))?; + let inbox_url = format!("{}://{domain}/inbox", http_protocol_str()); + let keypair = generate_actor_keypair()?; + let person_form = DbPersonForm { + username: username.to_string(), + ap_id, + inbox_url, + public_key: keypair.public_key, + private_key: Some(keypair.private_key), + last_refreshed_at: Utc::now(), + local: true, + }; + DbPerson::create(&person_form, data) + } + } } diff --git a/src/backend/federation/objects/edit.rs b/src/backend/federation/objects/edit.rs index 1d37cfd..f8353de 100644 --- a/src/backend/federation/objects/edit.rs +++ b/src/backend/federation/objects/edit.rs @@ -12,6 +12,7 @@ use activitypub_federation::{ traits::Object, }; use chrono::{DateTime, Utc}; +use log::warn; use serde::{Deserialize, Serialize}; use url::Url; @@ -77,8 +78,14 @@ impl Object for DbEdit { async fn from_json(json: Self::Kind, data: &Data) -> Result { let article = json.object.dereference(data).await?; - let creator = json.attributed_to.dereference(data).await?; - // TODO: if creator fails to fetch, make a dummy user + let creator = match json.attributed_to.dereference(data).await { + Ok(c) => c, + Err(e) => { + // If actor couldnt be fetched, use ghost as placeholder + warn!("Failed to fetch user {}: {e}", json.attributed_to); + DbPerson::ghost(data)? + } + }; let form = DbEditForm { creator_id: creator.id, ap_id: json.id, diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 4bec3e3..3670053 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -169,6 +169,9 @@ async fn setup(data: &Data) -> Result<(), Error> { ) .await?; + // create ghost user + DbPerson::ghost(data)?; + Ok(()) }