Remove remaining usages of unwrap() from activitypub code

This commit is contained in:
Felix Ableitner 2020-08-10 19:40:23 +02:00
parent 6b0bc1029f
commit 8c9928bcdf
9 changed files with 179 additions and 120 deletions

View file

@ -605,11 +605,11 @@ impl Perform for Oper<FollowCommunity> {
// Dont actually add to the community followers here, because you need // Dont actually add to the community followers here, because you need
// to wait for the accept // to wait for the accept
user user
.send_follow(&community.actor_id, &self.client, pool) .send_follow(&community.actor_id()?, &self.client, pool)
.await?; .await?;
} else { } else {
user user
.send_unfollow(&community.actor_id, &self.client, pool) .send_unfollow(&community.actor_id()?, &self.client, pool)
.await?; .await?;
let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form); let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form);
if blocking(pool, unfollow).await?.is_err() { if blocking(pool, unfollow).await?.is_err() {

View file

@ -21,7 +21,7 @@ use uuid::Uuid;
pub async fn send_activity_to_community( pub async fn send_activity_to_community(
creator: &User_, creator: &User_,
community: &Community, community: &Community,
to: Vec<String>, to: Vec<Url>,
activity: AnyBase, activity: AnyBase,
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
@ -43,17 +43,18 @@ pub async fn send_activity(
client: &Client, client: &Client,
activity: &AnyBase, activity: &AnyBase,
actor: &dyn ActorType, actor: &dyn ActorType,
to: Vec<String>, to: Vec<Url>,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let activity = serde_json::to_string(&activity)?; let activity = serde_json::to_string(&activity)?;
debug!("Sending activitypub activity {} to {:?}", activity, to); debug!("Sending activitypub activity {} to {:?}", activity, to);
for t in to { for to_url in to {
let to_url = Url::parse(&t)?;
check_is_apub_id_valid(&to_url)?; check_is_apub_id_valid(&to_url)?;
let res = retry_custom(|| async { let res = retry_custom(|| async {
let request = client.post(&t).header("Content-Type", "application/json"); let request = client
.post(to_url.as_str())
.header("Content-Type", "application/json");
match sign(request, actor, activity.clone()).await { match sign(request, actor, activity.clone()).await {
Ok(signed) => Ok(signed.send().await), Ok(signed) => Ok(signed.send().await),

View file

@ -302,7 +302,7 @@ impl ApubObjectType for Comment {
send_activity_to_community( send_activity_to_community(
&creator, &creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()?],
delete.into_any_base()?, delete.into_any_base()?,
client, client,
pool, pool,
@ -344,7 +344,7 @@ impl ApubObjectType for Comment {
send_activity_to_community( send_activity_to_community(
&creator, &creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()?],
undo.into_any_base()?, undo.into_any_base()?,
client, client,
pool, pool,
@ -377,7 +377,7 @@ impl ApubObjectType for Comment {
send_activity_to_community( send_activity_to_community(
&mod_, &mod_,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()?],
remove.into_any_base()?, remove.into_any_base()?,
client, client,
pool, pool,
@ -419,7 +419,7 @@ impl ApubObjectType for Comment {
send_activity_to_community( send_activity_to_community(
&mod_, &mod_,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()?],
undo.into_any_base()?, undo.into_any_base()?,
client, client,
pool, pool,
@ -455,7 +455,7 @@ impl ApubLikeableType for Comment {
send_activity_to_community( send_activity_to_community(
&creator, &creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()?],
like.into_any_base()?, like.into_any_base()?,
client, client,
pool, pool,
@ -488,7 +488,7 @@ impl ApubLikeableType for Comment {
send_activity_to_community( send_activity_to_community(
&creator, &creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()?],
dislike.into_any_base()?, dislike.into_any_base()?,
client, client,
pool, pool,
@ -529,7 +529,7 @@ impl ApubLikeableType for Comment {
send_activity_to_community( send_activity_to_community(
&creator, &creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()?],
undo.into_any_base()?, undo.into_any_base()?,
client, client,
pool, pool,
@ -541,7 +541,7 @@ impl ApubLikeableType for Comment {
struct MentionsAndAddresses { struct MentionsAndAddresses {
addressed_ccs: Vec<String>, addressed_ccs: Vec<String>,
inboxes: Vec<String>, inboxes: Vec<Url>,
tags: Vec<Mention>, tags: Vec<Mention>,
} }
@ -576,7 +576,7 @@ async fn collect_non_local_mentions_and_addresses(
.filter(|m| !m.is_local()) .filter(|m| !m.is_local())
.collect::<Vec<MentionData>>(); .collect::<Vec<MentionData>>();
let mut mention_inboxes = Vec::new(); let mut mention_inboxes: Vec<Url> = Vec::new();
for mention in &mentions { for mention in &mentions {
// TODO should it be fetching it every time? // TODO should it be fetching it every time?
if let Ok(actor_id) = fetch_webfinger_url(mention, client).await { if let Ok(actor_id) = fetch_webfinger_url(mention, client).await {
@ -584,7 +584,7 @@ async fn collect_non_local_mentions_and_addresses(
addressed_ccs.push(actor_id.to_owned().to_string()); addressed_ccs.push(actor_id.to_owned().to_string());
let mention_user = get_or_fetch_and_upsert_user(&actor_id, client, pool).await?; let mention_user = get_or_fetch_and_upsert_user(&actor_id, client, pool).await?;
let shared_inbox = mention_user.get_shared_inbox_url(); let shared_inbox = mention_user.get_shared_inbox_url()?;
mention_inboxes.push(shared_inbox); mention_inboxes.push(shared_inbox);
let mut mention_tag = Mention::new(); let mut mention_tag = Mention::new();
@ -593,7 +593,7 @@ async fn collect_non_local_mentions_and_addresses(
} }
} }
let mut inboxes = vec![community.get_shared_inbox_url()]; let mut inboxes = vec![community.get_shared_inbox_url()?];
inboxes.extend(mention_inboxes); inboxes.extend(mention_inboxes);
inboxes = inboxes.into_iter().unique().collect(); inboxes = inboxes.into_iter().unique().collect();

View file

@ -7,8 +7,7 @@ use crate::{
create_apub_tombstone_response, create_apub_tombstone_response,
create_tombstone, create_tombstone,
extensions::group_extensions::GroupExtension, extensions::group_extensions::GroupExtension,
fetcher::get_or_fetch_and_upsert_user, fetcher::{get_or_fetch_and_upsert_actor, get_or_fetch_and_upsert_user},
get_shared_inbox,
insert_activity, insert_activity,
ActorType, ActorType,
FromApub, FromApub,
@ -49,7 +48,7 @@ use lemmy_db::{
post::Post, post::Post,
user::User_, user::User_,
}; };
use lemmy_utils::{convert_datetime, location_info}; use lemmy_utils::{convert_datetime, get_apub_protocol_string, location_info};
use serde::Deserialize; use serde::Deserialize;
use url::Url; use url::Url;
@ -100,7 +99,7 @@ impl ToApub for Community {
.set_following(self.get_following_url().parse()?) .set_following(self.get_following_url().parse()?)
.set_liked(self.get_liked_url().parse()?) .set_liked(self.get_liked_url().parse()?)
.set_endpoints(Endpoints { .set_endpoints(Endpoints {
shared_inbox: Some(self.get_shared_inbox_url().parse()?), shared_inbox: Some(self.get_shared_inbox_url()?),
..Default::default() ..Default::default()
}); });
@ -114,7 +113,7 @@ impl ToApub for Community {
Ok(Ext2::new( Ok(Ext2::new(
ap_actor, ap_actor,
group_extension, group_extension,
self.get_public_key_ext(), self.get_public_key_ext()?,
)) ))
} }
@ -129,11 +128,11 @@ impl ActorType for Community {
self.actor_id.to_owned() self.actor_id.to_owned()
} }
fn public_key(&self) -> String { fn public_key(&self) -> Option<String> {
self.public_key.to_owned().unwrap() self.public_key.to_owned()
} }
fn private_key(&self) -> String { fn private_key(&self) -> Option<String> {
self.private_key.to_owned().unwrap() self.private_key.to_owned()
} }
/// As a local community, accept the follow request from a remote user. /// As a local community, accept the follow request from a remote user.
@ -146,11 +145,11 @@ impl ActorType for Community {
let actor_uri = follow let actor_uri = follow
.actor()? .actor()?
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.context(location_info!())? .context(location_info!())?;
.to_string(); let actor = get_or_fetch_and_upsert_actor(actor_uri, client, pool).await?;
let mut accept = Accept::new(self.actor_id.to_owned(), follow.into_any_base()?); let mut accept = Accept::new(self.actor_id.to_owned(), follow.into_any_base()?);
let to = format!("{}/inbox", actor_uri); let to = actor.get_inbox_url()?;
accept accept
.set_context(context()) .set_context(context())
.set_id(generate_activity_id(AcceptType::Accept)?) .set_id(generate_activity_id(AcceptType::Accept)?)
@ -284,7 +283,10 @@ impl ActorType for Community {
} }
/// For a given community, returns the inboxes of all followers. /// For a given community, returns the inboxes of all followers.
async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<String>, LemmyError> { ///
/// TODO: this function is very badly implemented, we should just store shared_inbox_url in
/// CommunityFollowerView
async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<Url>, LemmyError> {
let id = self.id; let id = self.id;
let inboxes = blocking(pool, move |conn| { let inboxes = blocking(pool, move |conn| {
@ -293,8 +295,22 @@ impl ActorType for Community {
.await??; .await??;
let inboxes = inboxes let inboxes = inboxes
.into_iter() .into_iter()
.map(|c| get_shared_inbox(&Url::parse(&c.user_actor_id).unwrap())) .map(|u| -> Result<Url, LemmyError> {
.filter(|s| !s.is_empty()) let url = Url::parse(&u.user_actor_id)?;
let domain = url.domain().context(location_info!())?;
let port = if let Some(port) = url.port() {
format!(":{}", port)
} else {
"".to_string()
};
Ok(Url::parse(&format!(
"{}://{}{}/inbox",
get_apub_protocol_string(),
domain,
port,
))?)
})
.filter_map(Result::ok)
.unique() .unique()
.collect(); .collect();
@ -303,7 +319,7 @@ impl ActorType for Community {
async fn send_follow( async fn send_follow(
&self, &self,
_follow_actor_id: &str, _follow_actor_id: &Url,
_client: &Client, _client: &Client,
_pool: &DbPool, _pool: &DbPool,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
@ -312,7 +328,7 @@ impl ActorType for Community {
async fn send_unfollow( async fn send_unfollow(
&self, &self,
_follow_actor_id: &str, _follow_actor_id: &Url,
_client: &Client, _client: &Client,
_pool: &DbPool, _pool: &DbPool,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
@ -510,13 +526,15 @@ pub async fn do_announce(
insert_activity(community.creator_id, announce.clone(), true, pool).await?; insert_activity(community.creator_id, announce.clone(), true, pool).await?;
let mut to = community.get_follower_inboxes(pool).await?; let mut to: Vec<Url> = community.get_follower_inboxes(pool).await?;
// dont send to the local instance, nor to the instance where the activity originally came from, // dont send to the local instance, nor to the instance where the activity originally came from,
// because that would result in a database error (same data inserted twice) // because that would result in a database error (same data inserted twice)
// this seems to be the "easiest" stable alternative for remove_item() // this seems to be the "easiest" stable alternative for remove_item()
to.retain(|x| *x != sender.get_shared_inbox_url()); let sender_shared_inbox = sender.get_shared_inbox_url()?;
to.retain(|x| *x != community.get_shared_inbox_url()); to.retain(|x| x != &sender_shared_inbox);
let community_shared_inbox = community.get_shared_inbox_url()?;
to.retain(|x| x != &community_shared_inbox);
send_activity(client, &announce.into_any_base()?, community, to).await?; send_activity(client, &announce.into_any_base()?, community, to).await?;

View file

@ -2,11 +2,12 @@ use crate::{apub::ActorType, LemmyError};
use activitystreams::unparsed::UnparsedMutExt; use activitystreams::unparsed::UnparsedMutExt;
use activitystreams_ext::UnparsedExtension; use activitystreams_ext::UnparsedExtension;
use actix_web::{client::ClientRequest, HttpRequest}; use actix_web::{client::ClientRequest, HttpRequest};
use anyhow::anyhow; use anyhow::{anyhow, Context};
use http_signature_normalization_actix::{ use http_signature_normalization_actix::{
digest::{DigestClient, SignExt}, digest::{DigestClient, SignExt},
Config, Config,
}; };
use lemmy_utils::location_info;
use log::debug; use log::debug;
use openssl::{ use openssl::{
hash::MessageDigest, hash::MessageDigest,
@ -27,7 +28,7 @@ pub async fn sign(
activity: String, activity: String,
) -> Result<DigestClient<String>, LemmyError> { ) -> Result<DigestClient<String>, LemmyError> {
let signing_key_id = format!("{}#main-key", actor.actor_id()?); let signing_key_id = format!("{}#main-key", actor.actor_id()?);
let private_key = actor.private_key(); let private_key = actor.private_key().context(location_info!())?;
let digest_client = request let digest_client = request
.signature_with_digest( .signature_with_digest(
@ -49,6 +50,7 @@ pub async fn sign(
} }
pub fn verify(request: &HttpRequest, actor: &dyn ActorType) -> Result<(), LemmyError> { pub fn verify(request: &HttpRequest, actor: &dyn ActorType) -> Result<(), LemmyError> {
let public_key = actor.public_key().context(location_info!())?;
let verified = HTTP_SIG_CONFIG let verified = HTTP_SIG_CONFIG
.begin_verify( .begin_verify(
request.method(), request.method(),
@ -58,10 +60,9 @@ pub fn verify(request: &HttpRequest, actor: &dyn ActorType) -> Result<(), LemmyE
.verify(|signature, signing_string| -> Result<bool, LemmyError> { .verify(|signature, signing_string| -> Result<bool, LemmyError> {
debug!( debug!(
"Verifying with key {}, message {}", "Verifying with key {}, message {}",
&actor.public_key(), &public_key, &signing_string
&signing_string
); );
let public_key = PKey::public_key_from_pem(actor.public_key().as_bytes())?; let public_key = PKey::public_key_from_pem(public_key.as_bytes())?;
let mut verifier = Verifier::new(MessageDigest::sha256(), &public_key)?; let mut verifier = Verifier::new(MessageDigest::sha256(), &public_key)?;
verifier.update(&signing_string.as_bytes())?; verifier.update(&signing_string.as_bytes())?;
Ok(verifier.verify(&base64::decode(signature)?)?) Ok(verifier.verify(&base64::decode(signature)?)?)

View file

@ -240,25 +240,13 @@ pub trait ApubLikeableType {
) -> Result<(), LemmyError>; ) -> Result<(), LemmyError>;
} }
pub fn get_shared_inbox(actor_id: &Url) -> String {
format!(
"{}://{}{}/inbox",
&actor_id.scheme(),
&actor_id.host_str().unwrap(),
if let Some(port) = actor_id.port() {
format!(":{}", port)
} else {
"".to_string()
},
)
}
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
pub trait ActorType { pub trait ActorType {
fn actor_id_str(&self) -> String; fn actor_id_str(&self) -> String;
fn public_key(&self) -> String; // TODO: every actor should have a public key, so this shouldnt be an option (needs to be fixed in db)
fn private_key(&self) -> String; fn public_key(&self) -> Option<String>;
fn private_key(&self) -> Option<String>;
/// numeric id in the database, used for insert_activity /// numeric id in the database, used for insert_activity
fn user_id(&self) -> i32; fn user_id(&self) -> i32;
@ -268,13 +256,13 @@ pub trait ActorType {
#[allow(unused_variables)] #[allow(unused_variables)]
async fn send_follow( async fn send_follow(
&self, &self,
follow_actor_id: &str, follow_actor_id: &Url,
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
) -> Result<(), LemmyError>; ) -> Result<(), LemmyError>;
async fn send_unfollow( async fn send_unfollow(
&self, &self,
follow_actor_id: &str, follow_actor_id: &Url,
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
) -> Result<(), LemmyError>; ) -> Result<(), LemmyError>;
@ -314,7 +302,7 @@ pub trait ActorType {
) -> Result<(), LemmyError>; ) -> Result<(), LemmyError>;
/// For a given community, returns the inboxes of all followers. /// For a given community, returns the inboxes of all followers.
async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<String>, LemmyError>; async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<Url>, LemmyError>;
fn actor_id(&self) -> Result<Url, ParseError> { fn actor_id(&self) -> Result<Url, ParseError> {
Url::parse(&self.actor_id_str()) Url::parse(&self.actor_id_str())
@ -325,9 +313,19 @@ pub trait ActorType {
Url::parse(&format!("{}/inbox", &self.actor_id_str())) Url::parse(&format!("{}/inbox", &self.actor_id_str()))
} }
// TODO: make this return `Result<Url, ParseError> fn get_shared_inbox_url(&self) -> Result<Url, LemmyError> {
fn get_shared_inbox_url(&self) -> String { let actor_id = self.actor_id()?;
get_shared_inbox(&self.actor_id().unwrap()) let url = format!(
"{}://{}{}/inbox",
&actor_id.scheme(),
&actor_id.host_str().context(location_info!())?,
if let Some(port) = actor_id.port() {
format!(":{}", port)
} else {
"".to_string()
},
);
Ok(Url::parse(&url)?)
} }
fn get_outbox_url(&self) -> Result<Url, ParseError> { fn get_outbox_url(&self) -> Result<Url, ParseError> {
@ -346,13 +344,15 @@ pub trait ActorType {
format!("{}/liked", &self.actor_id_str()) format!("{}/liked", &self.actor_id_str())
} }
fn get_public_key_ext(&self) -> PublicKeyExtension { fn get_public_key_ext(&self) -> Result<PublicKeyExtension, LemmyError> {
PublicKey { Ok(
id: format!("{}#main-key", self.actor_id_str()), PublicKey {
owner: self.actor_id_str(), id: format!("{}#main-key", self.actor_id_str()),
public_key_pem: self.public_key(), owner: self.actor_id_str(),
} public_key_pem: self.public_key().context(location_info!())?,
.to_ext() }
.to_ext(),
)
} }
} }

View file

@ -32,7 +32,7 @@ use activitystreams::{
Update, Update,
}, },
context, context,
object::{kind::PageType, Image, Page, Tombstone}, object::{kind::PageType, Image, Object, Page, Tombstone},
prelude::*, prelude::*,
public, public,
}; };
@ -148,6 +148,50 @@ impl ToApub for Post {
} }
} }
struct EmbedType {
title: Option<String>,
description: Option<String>,
html: Option<String>,
}
fn extract_embed_from_apub(
page: &Ext1<Object<PageType>, PageExtension>,
) -> Result<EmbedType, LemmyError> {
match page.inner.preview() {
Some(preview) => {
let preview_page = Page::from_any_base(preview.one().context(location_info!())?.to_owned())?
.context(location_info!())?;
let title = preview_page
.name()
.map(|n| n.one())
.flatten()
.map(|s| s.as_xsd_string())
.flatten()
.map(|s| s.to_string());
let description = preview_page
.summary()
.map(|s| s.as_single_xsd_string())
.flatten()
.map(|s| s.to_string());
let html = preview_page
.content()
.map(|c| c.as_single_xsd_string())
.flatten()
.map(|s| s.to_string());
Ok(EmbedType {
title,
description,
html,
})
}
None => Ok(EmbedType {
title: None,
description: None,
html: None,
}),
}
}
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl FromApub for PostForm { impl FromApub for PostForm {
type ApubType = PageExt; type ApubType = PageExt;
@ -196,22 +240,7 @@ impl FromApub for PostForm {
None => None, None => None,
}; };
let (embed_title, embed_description, embed_html) = match page.inner.preview() { let embed = extract_embed_from_apub(page)?;
Some(preview) => {
let preview_page = Page::from_any_base(preview.one().unwrap().to_owned())?.unwrap();
let name = preview_page
.name()
.map(|n| n.as_one().unwrap().as_xsd_string().unwrap().to_string());
let summary = preview_page
.summary()
.map(|s| s.as_single_xsd_string().unwrap().to_string());
let content = preview_page
.content()
.map(|c| c.as_single_xsd_string().unwrap().to_string());
(name, summary, content)
}
None => (None, None, None),
};
let name = page let name = page
.inner .inner
@ -225,12 +254,16 @@ impl FromApub for PostForm {
.inner .inner
.url() .url()
.as_ref() .as_ref()
.map(|u| u.as_single_xsd_string().unwrap().to_string()); .map(|u| u.as_single_xsd_string())
.flatten()
.map(|s| s.to_string());
let body = page let body = page
.inner .inner
.content() .content()
.as_ref() .as_ref()
.map(|c| c.as_single_xsd_string().unwrap().to_string()); .map(|c| c.as_single_xsd_string())
.flatten()
.map(|s| s.to_string());
check_slurs(&name)?; check_slurs(&name)?;
let body_slurs_removed = body.map(|b| remove_slurs(&b)); let body_slurs_removed = body.map(|b| remove_slurs(&b));
Ok(PostForm { Ok(PostForm {
@ -254,9 +287,9 @@ impl FromApub for PostForm {
deleted: None, deleted: None,
nsfw: ext.sensitive, nsfw: ext.sensitive,
stickied: Some(ext.stickied), stickied: Some(ext.stickied),
embed_title, embed_title: embed.title,
embed_description, embed_description: embed.description,
embed_html, embed_html: embed.html,
thumbnail_url, thumbnail_url,
ap_id: check_actor_domain(page, expected_domain)?, ap_id: check_actor_domain(page, expected_domain)?,
local: false, local: false,
@ -288,7 +321,7 @@ impl ApubObjectType for Post {
send_activity_to_community( send_activity_to_community(
creator, creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()?],
create.into_any_base()?, create.into_any_base()?,
client, client,
pool, pool,
@ -319,7 +352,7 @@ impl ApubObjectType for Post {
send_activity_to_community( send_activity_to_community(
creator, creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()?],
update.into_any_base()?, update.into_any_base()?,
client, client,
pool, pool,
@ -349,7 +382,7 @@ impl ApubObjectType for Post {
send_activity_to_community( send_activity_to_community(
creator, creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()?],
delete.into_any_base()?, delete.into_any_base()?,
client, client,
pool, pool,
@ -387,7 +420,7 @@ impl ApubObjectType for Post {
send_activity_to_community( send_activity_to_community(
creator, creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()?],
undo.into_any_base()?, undo.into_any_base()?,
client, client,
pool, pool,
@ -417,7 +450,7 @@ impl ApubObjectType for Post {
send_activity_to_community( send_activity_to_community(
mod_, mod_,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()?],
remove.into_any_base()?, remove.into_any_base()?,
client, client,
pool, pool,
@ -455,7 +488,7 @@ impl ApubObjectType for Post {
send_activity_to_community( send_activity_to_community(
mod_, mod_,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()?],
undo.into_any_base()?, undo.into_any_base()?,
client, client,
pool, pool,
@ -488,7 +521,7 @@ impl ApubLikeableType for Post {
send_activity_to_community( send_activity_to_community(
&creator, &creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()?],
like.into_any_base()?, like.into_any_base()?,
client, client,
pool, pool,
@ -518,7 +551,7 @@ impl ApubLikeableType for Post {
send_activity_to_community( send_activity_to_community(
&creator, &creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()?],
dislike.into_any_base()?, dislike.into_any_base()?,
client, client,
pool, pool,
@ -556,7 +589,7 @@ impl ApubLikeableType for Post {
send_activity_to_community( send_activity_to_community(
&creator, &creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()?],
undo.into_any_base()?, undo.into_any_base()?,
client, client,
pool, pool,

View file

@ -6,6 +6,7 @@ use crate::{
create_tombstone, create_tombstone,
fetcher::get_or_fetch_and_upsert_user, fetcher::get_or_fetch_and_upsert_user,
insert_activity, insert_activity,
ActorType,
ApubObjectType, ApubObjectType,
FromApub, FromApub,
ToApub, ToApub,
@ -132,7 +133,7 @@ impl ApubObjectType for PrivateMessage {
let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??; let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??;
let mut create = Create::new(creator.actor_id.to_owned(), note.into_any_base()?); let mut create = Create::new(creator.actor_id.to_owned(), note.into_any_base()?);
let to = format!("{}/inbox", recipient.actor_id); let to = recipient.get_inbox_url()?;
create create
.set_context(context()) .set_context(context())
.set_id(generate_activity_id(CreateType::Create)?) .set_id(generate_activity_id(CreateType::Create)?)
@ -157,7 +158,7 @@ impl ApubObjectType for PrivateMessage {
let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??; let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??;
let mut update = Update::new(creator.actor_id.to_owned(), note.into_any_base()?); let mut update = Update::new(creator.actor_id.to_owned(), note.into_any_base()?);
let to = format!("{}/inbox", recipient.actor_id); let to = recipient.get_inbox_url()?;
update update
.set_context(context()) .set_context(context())
.set_id(generate_activity_id(UpdateType::Update)?) .set_id(generate_activity_id(UpdateType::Update)?)
@ -181,7 +182,7 @@ impl ApubObjectType for PrivateMessage {
let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??; let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??;
let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?); let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?);
let to = format!("{}/inbox", recipient.actor_id); let to = recipient.get_inbox_url()?;
delete delete
.set_context(context()) .set_context(context())
.set_id(generate_activity_id(DeleteType::Delete)?) .set_id(generate_activity_id(DeleteType::Delete)?)
@ -205,7 +206,7 @@ impl ApubObjectType for PrivateMessage {
let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??; let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??;
let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?); let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?);
let to = format!("{}/inbox", recipient.actor_id); let to = recipient.get_inbox_url()?;
delete delete
.set_context(context()) .set_context(context())
.set_id(generate_activity_id(DeleteType::Delete)?) .set_id(generate_activity_id(DeleteType::Delete)?)

View file

@ -4,6 +4,7 @@ use crate::{
activities::{generate_activity_id, send_activity}, activities::{generate_activity_id, send_activity},
check_actor_domain, check_actor_domain,
create_apub_response, create_apub_response,
fetcher::get_or_fetch_and_upsert_actor,
insert_activity, insert_activity,
ActorType, ActorType,
FromApub, FromApub,
@ -83,7 +84,7 @@ impl ToApub for User_ {
.set_following(self.get_following_url().parse()?) .set_following(self.get_following_url().parse()?)
.set_liked(self.get_liked_url().parse()?) .set_liked(self.get_liked_url().parse()?)
.set_endpoints(Endpoints { .set_endpoints(Endpoints {
shared_inbox: Some(self.get_shared_inbox_url().parse()?), shared_inbox: Some(self.get_shared_inbox_url()?),
..Default::default() ..Default::default()
}); });
@ -91,7 +92,7 @@ impl ToApub for User_ {
ap_actor.set_preferred_username(i.to_owned()); ap_actor.set_preferred_username(i.to_owned());
} }
Ok(Ext1::new(ap_actor, self.get_public_key_ext())) Ok(Ext1::new(ap_actor, self.get_public_key_ext()?))
} }
fn to_tombstone(&self) -> Result<Tombstone, LemmyError> { fn to_tombstone(&self) -> Result<Tombstone, LemmyError> {
unimplemented!() unimplemented!()
@ -104,26 +105,27 @@ impl ActorType for User_ {
self.actor_id.to_owned() self.actor_id.to_owned()
} }
fn public_key(&self) -> String { fn public_key(&self) -> Option<String> {
self.public_key.to_owned().unwrap() self.public_key.to_owned()
} }
fn private_key(&self) -> String { fn private_key(&self) -> Option<String> {
self.private_key.to_owned().unwrap() self.private_key.to_owned()
} }
/// As a given local user, send out a follow request to a remote community. /// As a given local user, send out a follow request to a remote community.
async fn send_follow( async fn send_follow(
&self, &self,
follow_actor_id: &str, follow_actor_id: &Url,
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let mut follow = Follow::new(self.actor_id.to_owned(), follow_actor_id); let mut follow = Follow::new(self.actor_id.to_owned(), follow_actor_id.as_str());
follow follow
.set_context(context()) .set_context(context())
.set_id(generate_activity_id(FollowType::Follow)?); .set_id(generate_activity_id(FollowType::Follow)?);
let to = format!("{}/inbox", follow_actor_id); let follow_actor = get_or_fetch_and_upsert_actor(follow_actor_id, client, pool).await?;
let to = follow_actor.get_inbox_url()?;
insert_activity(self.id, follow.clone(), true, pool).await?; insert_activity(self.id, follow.clone(), true, pool).await?;
@ -133,16 +135,17 @@ impl ActorType for User_ {
async fn send_unfollow( async fn send_unfollow(
&self, &self,
follow_actor_id: &str, follow_actor_id: &Url,
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let mut follow = Follow::new(self.actor_id.to_owned(), follow_actor_id); let mut follow = Follow::new(self.actor_id.to_owned(), follow_actor_id.as_str());
follow follow
.set_context(context()) .set_context(context())
.set_id(generate_activity_id(FollowType::Follow)?); .set_id(generate_activity_id(FollowType::Follow)?);
let follow_actor = get_or_fetch_and_upsert_actor(follow_actor_id, client, pool).await?;
let to = format!("{}/inbox", follow_actor_id); let to = follow_actor.get_inbox_url()?;
// Undo that fake activity // Undo that fake activity
let mut undo = Undo::new(Url::parse(&self.actor_id)?, follow.into_any_base()?); let mut undo = Undo::new(Url::parse(&self.actor_id)?, follow.into_any_base()?);
@ -201,7 +204,7 @@ impl ActorType for User_ {
unimplemented!() unimplemented!()
} }
async fn get_follower_inboxes(&self, _pool: &DbPool) -> Result<Vec<String>, LemmyError> { async fn get_follower_inboxes(&self, _pool: &DbPool) -> Result<Vec<Url>, LemmyError> {
unimplemented!() unimplemented!()
} }
@ -257,7 +260,9 @@ impl FromApub for UserForm {
let bio = person let bio = person
.inner .inner
.summary() .summary()
.map(|s| s.as_single_xsd_string().unwrap().into()); .map(|s| s.as_single_xsd_string())
.flatten()
.map(|s| s.to_string());
check_slurs(&name)?; check_slurs(&name)?;
check_slurs_opt(&preferred_username)?; check_slurs_opt(&preferred_username)?;
check_slurs_opt(&bio)?; check_slurs_opt(&bio)?;