summaryrefslogtreecommitdiffstats
path: root/server/src/apub
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/apub')
-rw-r--r--server/src/apub/activities.rs12
-rw-r--r--server/src/apub/comment.rs20
-rw-r--r--server/src/apub/community.rs220
-rw-r--r--server/src/apub/community_inbox.rs12
-rw-r--r--server/src/apub/extensions/group_extensions.rs6
-rw-r--r--server/src/apub/extensions/signatures.rs18
-rw-r--r--server/src/apub/fetcher.rs110
-rw-r--r--server/src/apub/mod.rs78
-rw-r--r--server/src/apub/post.rs18
-rw-r--r--server/src/apub/private_message.rs16
-rw-r--r--server/src/apub/shared_inbox.rs117
-rw-r--r--server/src/apub/user.rs124
-rw-r--r--server/src/apub/user_inbox.rs36
13 files changed, 374 insertions, 413 deletions
diff --git a/server/src/apub/activities.rs b/server/src/apub/activities.rs
index e5dc7045..204a380d 100644
--- a/server/src/apub/activities.rs
+++ b/server/src/apub/activities.rs
@@ -1,12 +1,18 @@
use crate::{
- apub::{extensions::signatures::sign, is_apub_id_valid, ActorType},
- db::{activity::insert_activity, community::Community, user::User_},
+ apub::{
+ community::do_announce,
+ extensions::signatures::sign,
+ insert_activity,
+ is_apub_id_valid,
+ ActorType,
+ },
request::retry_custom,
DbPool,
LemmyError,
};
use activitystreams::{context, object::properties::ObjectProperties, public, Activity, Base};
use actix_web::client::Client;
+use lemmy_db::{community::Community, user::User_};
use log::debug;
use serde::Serialize;
use std::fmt::Debug;
@@ -43,7 +49,7 @@ where
// if this is a local community, we need to do an announce from the community instead
if community.local {
- Community::do_announce(activity, &community, creator, client, pool).await?;
+ do_announce(activity, &community, creator, client, pool).await?;
} else {
send_activity(client, &activity, creator, to).await?;
}
diff --git a/server/src/apub/comment.rs b/server/src/apub/comment.rs
index a42a52c2..af3581cb 100644
--- a/server/src/apub/comment.rs
+++ b/server/src/apub/comment.rs
@@ -17,19 +17,9 @@ use crate::{
ToApub,
},
blocking,
- convert_datetime,
- db::{
- comment::{Comment, CommentForm},
- community::Community,
- post::Post,
- user::User_,
- Crud,
- },
routes::DbPoolParam,
- scrape_text_for_mentions,
DbPool,
LemmyError,
- MentionData,
};
use activitystreams::{
activity::{Create, Delete, Dislike, Like, Remove, Undo, Update},
@@ -40,6 +30,14 @@ use activitystreams::{
use activitystreams_new::object::Tombstone;
use actix_web::{body::Body, client::Client, web::Path, HttpResponse};
use itertools::Itertools;
+use lemmy_db::{
+ comment::{Comment, CommentForm},
+ community::Community,
+ post::Post,
+ user::User_,
+ Crud,
+};
+use lemmy_utils::{convert_datetime, scrape_text_for_mentions, MentionData};
use log::debug;
use serde::Deserialize;
@@ -123,7 +121,7 @@ impl FromApub for CommentForm {
/// Parse an ActivityPub note received from another instance into a Lemmy comment
async fn from_apub(
- note: &Note,
+ note: &mut Note,
client: &Client,
pool: &DbPool,
) -> Result<CommentForm, LemmyError> {
diff --git a/server/src/apub/community.rs b/server/src/apub/community.rs
index f866511c..8b623e71 100644
--- a/server/src/apub/community.rs
+++ b/server/src/apub/community.rs
@@ -4,44 +4,48 @@ use crate::{
create_apub_response,
create_apub_tombstone_response,
create_tombstone,
- extensions::{group_extensions::GroupExtension, signatures::PublicKey},
+ extensions::group_extensions::GroupExtension,
fetcher::get_or_fetch_and_upsert_remote_user,
get_shared_inbox,
+ insert_activity,
ActorType,
FromApub,
GroupExt,
ToApub,
},
blocking,
- convert_datetime,
- db::{
- activity::insert_activity,
- community::{Community, CommunityForm},
- community_view::{CommunityFollowerView, CommunityModeratorView},
- user::User_,
- },
- naive_now,
routes::DbPoolParam,
DbPool,
LemmyError,
};
use activitystreams::{
activity::{Accept, Announce, Delete, Remove, Undo},
- actor::{kind::GroupType, properties::ApActorProperties, Group},
- collection::UnorderedCollection,
- context,
- endpoint::EndpointProperties,
- object::properties::ObjectProperties,
Activity,
Base,
BaseBox,
};
-use activitystreams_ext::Ext3;
-use activitystreams_new::{activity::Follow, object::Tombstone};
+use activitystreams_ext::Ext2;
+use activitystreams_new::{
+ activity::Follow,
+ actor::{kind::GroupType, ApActor, Endpoints, Group},
+ base::BaseExt,
+ collection::UnorderedCollection,
+ context,
+ object::Tombstone,
+ prelude::*,
+ primitives::{XsdAnyUri, XsdDateTime},
+};
use actix_web::{body::Body, client::Client, web, HttpResponse};
use itertools::Itertools;
+use lemmy_db::{
+ community::{Community, CommunityForm},
+ community_view::{CommunityFollowerView, CommunityModeratorView},
+ naive_now,
+ user::User_,
+};
+use lemmy_utils::convert_datetime;
use serde::{Deserialize, Serialize};
-use std::fmt::Debug;
+use std::{fmt::Debug, str::FromStr};
#[derive(Deserialize)]
pub struct CommunityQuery {
@@ -54,9 +58,6 @@ impl ToApub for Community {
// Turn a Lemmy Community into an ActivityPub group that can be sent out over the network.
async fn to_apub(&self, pool: &DbPool) -> Result<GroupExt, LemmyError> {
- let mut group = Group::default();
- let oprops: &mut ObjectProperties = group.as_mut();
-
// The attributed to, is an ordered vector with the creator actor_ids first,
// then the rest of the moderators
// TODO Technically the instance admins can mod the community, but lets
@@ -66,36 +67,36 @@ impl ToApub for Community {
CommunityModeratorView::for_community(&conn, id)
})
.await??;
- let moderators = moderators.into_iter().map(|m| m.user_actor_id).collect();
+ let moderators: Vec<String> = moderators.into_iter().map(|m| m.user_actor_id).collect();
- oprops
- .set_context_xsd_any_uri(context())?
- .set_id(self.actor_id.to_owned())?
- .set_name_xsd_string(self.name.to_owned())?
- .set_published(convert_datetime(self.published))?
- .set_many_attributed_to_xsd_any_uris(moderators)?;
+ let mut group = Group::new();
+ group
+ .set_context(context())
+ .set_id(XsdAnyUri::from_str(&self.actor_id)?)
+ .set_name(self.name.to_owned())
+ .set_published(XsdDateTime::from(convert_datetime(self.published)))
+ .set_many_attributed_tos(moderators);
if let Some(u) = self.updated.to_owned() {
- oprops.set_updated(convert_datetime(u))?;
+ group.set_updated(XsdDateTime::from(convert_datetime(u)));
}
if let Some(d) = self.description.to_owned() {
// TODO: this should be html, also add source field with raw markdown
// -> same for post.content and others
- oprops.set_content_xsd_string(d)?;
+ group.set_content(d);
}
- let mut endpoint_props = EndpointProperties::default();
-
- endpoint_props.set_shared_inbox(self.get_shared_inbox_url())?;
-
- let mut actor_props = ApActorProperties::default();
-
- actor_props
- .set_preferred_username(self.title.to_owned())?
- .set_inbox(self.get_inbox_url())?
- .set_outbox(self.get_outbox_url())?
- .set_endpoints(endpoint_props)?
- .set_followers(self.get_followers_url())?;
+ let mut ap_actor = ApActor::new(self.get_inbox_url().parse()?, group);
+ ap_actor
+ .set_preferred_username(self.title.to_owned())
+ .set_outbox(self.get_outbox_url().parse()?)
+ .set_followers(self.get_followers_url().parse()?)
+ .set_following(self.get_following_url().parse()?)
+ .set_liked(self.get_liked_url().parse()?)
+ .set_endpoints(Endpoints {
+ shared_inbox: Some(self.get_shared_inbox_url().parse()?),
+ ..Default::default()
+ });
let nsfw = self.nsfw;
let category_id = self.category_id;
@@ -104,10 +105,9 @@ impl ToApub for Community {
})
.await??;
- Ok(Ext3::new(
- group,
+ Ok(Ext2::new(
+ ap_actor,
group_extension,
- actor_props,
self.get_public_key_ext(),
))
}
@@ -367,38 +367,52 @@ impl FromApub for CommunityForm {
type ApubType = GroupExt;
/// Parse an ActivityPub group received from another instance into a Lemmy community.
- async fn from_apub(group: &GroupExt, client: &Client, pool: &DbPool) -> Result<Self, LemmyError> {
- let group_extensions: &GroupExtension = &group.ext_one;
- let oprops = &group.inner.object_props;
- let aprops = &group.ext_two;
- let public_key: &PublicKey = &group.ext_three.public_key;
-
- let mut creator_and_moderator_uris = oprops.get_many_attributed_to_xsd_any_uris().unwrap();
- let creator_uri = creator_and_moderator_uris.next().unwrap();
+ async fn from_apub(
+ group: &mut GroupExt,
+ client: &Client,
+ pool: &DbPool,
+ ) -> Result<Self, LemmyError> {
+ // TODO: this is probably gonna cause problems cause fetcher:292 also calls take_attributed_to()
+ let creator_and_moderator_uris = group.clone().take_attributed_to().unwrap();
+ let creator_uri = creator_and_moderator_uris
+ .as_many()
+ .unwrap()
+ .iter()
+ .next()
+ .unwrap()
+ .as_xsd_any_uri()
+ .unwrap();
let creator = get_or_fetch_and_upsert_remote_user(creator_uri.as_str(), client, pool).await?;
Ok(CommunityForm {
- name: oprops.get_name_xsd_string().unwrap().to_string(),
- title: aprops.get_preferred_username().unwrap().to_string(),
+ name: group
+ .take_name()
+ .unwrap()
+ .as_single_xsd_string()
+ .unwrap()
+ .into(),
+ title: group.inner.take_preferred_username().unwrap(),
// TODO: should be parsed as html and tags like <script> removed (or use markdown source)
// -> same for post.content etc
- description: oprops.get_content_xsd_string().map(|s| s.to_string()),
- category_id: group_extensions.category.identifier.parse::<i32>()?,
+ description: group
+ .take_content()
+ .map(|s| s.as_single_xsd_string().unwrap().into()),
+ category_id: group.ext_one.category.identifier.parse::<i32>()?,
creator_id: creator.id,
removed: None,
- published: oprops
- .get_published()
+ published: group
+ .take_published()
.map(|u| u.as_ref().to_owned().naive_local()),
- updated: oprops
- .get_updated()
+ updated: group
+ .take_updated()
.map(|u| u.as_ref().to_owned().naive_local()),
deleted: None,
- nsfw: group_extensions.sensitive,
- actor_id: oprops.get_id().unwrap().to_string(),
+ nsfw: group.ext_one.sensitive,
+ actor_id: group.id().unwrap().to_string(),
local: false,
private_key: None,
- public_key: Some(public_key.to_owned().public_key_pem),
+ public_key: Some(group.ext_two.to_owned().public_key.public_key_pem),
last_refreshed_at: Some(naive_now()),
})
}
@@ -439,50 +453,46 @@ pub async fn get_apub_community_followers(
})
.await??;
- let mut collection = UnorderedCollection::default();
- let oprops: &mut ObjectProperties = collection.as_mut();
- oprops
- .set_context_xsd_any_uri(context())?
- .set_id(community.actor_id)?;
+ let mut collection = UnorderedCollection::new(vec![]);
collection
- .collection_props
- .set_total_items(community_followers.len() as u64)?;
+ .set_context(context())
+ // TODO: this needs its own ID
+ .set_id(community.actor_id.parse()?)
+ .set_total_items(community_followers.len() as u64);
Ok(create_apub_response(&collection))
}
-impl Community {
- pub async fn do_announce<A>(
- activity: A,
- community: &Community,
- sender: &dyn ActorType,
- client: &Client,
- pool: &DbPool,
- ) -> Result<HttpResponse, LemmyError>
- where
- A: Activity + Base + Serialize + Debug,
- {
- let mut announce = Announce::default();
- populate_object_props(
- &mut announce.object_props,
- vec![community.get_followers_url()],
- &format!("{}/announce/{}", community.actor_id, uuid::Uuid::new_v4()),
- )?;
- announce
- .announce_props
- .set_actor_xsd_any_uri(community.actor_id.to_owned())?
- .set_object_base_box(BaseBox::from_concrete(activity)?)?;
-
- insert_activity(community.creator_id, announce.clone(), true, pool).await?;
-
- // dont send to the instance where the activity originally came from, because that would result
- // in a database error (same data inserted twice)
- let mut to = community.get_follower_inboxes(pool).await?;
-
- // this seems to be the "easiest" stable alternative for remove_item()
- to.retain(|x| *x != sender.get_shared_inbox_url());
-
- send_activity(client, &announce, community, to).await?;
-
- Ok(HttpResponse::Ok().finish())
- }
+pub async fn do_announce<A>(
+ activity: A,
+ community: &Community,
+ sender: &dyn ActorType,
+ client: &Client,
+ pool: &DbPool,
+) -> Result<HttpResponse, LemmyError>
+where
+ A: Activity + Base + Serialize + Debug,
+{
+ let mut announce = Announce::default();
+ populate_object_props(
+ &mut announce.object_props,
+ vec![community.get_followers_url()],
+ &format!("{}/announce/{}", community.actor_id, uuid::Uuid::new_v4()),
+ )?;
+ announce
+ .announce_props
+ .set_actor_xsd_any_uri(community.actor_id.to_owned())?
+ .set_object_base_box(BaseBox::from_concrete(activity)?)?;
+
+ insert_activity(community.creator_id, announce.clone(), true, pool).await?;
+
+ // dont send to the instance where the activity originally came from, because that would result
+ // in a database error (same data inserted twice)
+ let mut to = community.get_follower_inboxes(pool).await?;
+
+ // this seems to be the "easiest" stable alternative for remove_item()
+ to.retain(|x| *x != sender.get_shared_inbox_url());
+
+ send_activity(client, &announce, community, to).await?;
+
+ Ok(HttpResponse::Ok().finish())
}
diff --git a/server/src/apub/community_inbox.rs b/server/src/apub/community_inbox.rs
index 996e0c25..8ea64434 100644
--- a/server/src/apub/community_inbox.rs
+++ b/server/src/apub/community_inbox.rs
@@ -2,21 +2,21 @@ use crate::{
apub::{
extensions::signatures::verify,
fetcher::{get_or_fetch_and_upsert_remote_community, get_or_fetch_and_upsert_remote_user},
+ insert_activity,
ActorType,
},
blocking,
- db::{
- activity::insert_activity,
- community::{Community, CommunityFollower, CommunityFollowerForm},
- user::User_,
- Followable,
- },
routes::{ChatServerParam, DbPoolParam},
LemmyError,
};
use activitystreams::activity::Undo;
use activitystreams_new::activity::Follow;
use actix_web::{client::Client, web, HttpRequest, HttpResponse};
+use lemmy_db::{
+ community::{Community, CommunityFollower, CommunityFollowerForm},
+ user::User_,
+ Followable,
+};
use log::debug;
use serde::Deserialize;
use std::fmt::Debug;
diff --git a/server/src/apub/extensions/group_extensions.rs b/server/src/apub/extensions/group_extensions.rs
index 1c24eef5..2120f6f1 100644
--- a/server/src/apub/extensions/group_extensions.rs
+++ b/server/src/apub/extensions/group_extensions.rs
@@ -1,9 +1,7 @@
-use crate::{
- db::{category::Category, Crud},
- LemmyError,
-};
+use crate::LemmyError;
use activitystreams::{ext::Extension, Actor};
use diesel::PgConnection;
+use lemmy_db::{category::Category, Crud};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
diff --git a/server/src/apub/extensions/signatures.rs b/server/src/apub/extensions/signatures.rs
index af46bc5e..1c930a95 100644
--- a/server/src/apub/extensions/signatures.rs
+++ b/server/src/apub/extensions/signatures.rs
@@ -9,7 +9,6 @@ use log::debug;
use openssl::{
hash::MessageDigest,
pkey::PKey,
- rsa::Rsa,
sign::{Signer, Verifier},
};
use serde::{Deserialize, Serialize};
@@ -19,23 +18,6 @@ lazy_static! {
static ref HTTP_SIG_CONFIG: Config = Config::new();
}
-pub struct Keypair {
- pub private_key: String,
- pub public_key: String,
-}
-
-/// Generate the asymmetric keypair for ActivityPub HTTP signatures.
-pub fn generate_actor_keypair() -> Result<Keypair, LemmyError> {
- let rsa = Rsa::generate(2048)?;
- let pkey = PKey::from_rsa(rsa)?;
- let public_key = pkey.public_key_to_pem()?;
- let private_key = pkey.private_key_to_pem_pkcs8()?;
- Ok(Keypair {
- private_key: String::from_utf8(private_key)?,
- public_key: String::from_utf8(public_key)?,
- })
-}
-
/// Signs request headers with the given keypair.
pub async fn sign(
request: ClientRequest,
diff --git a/server/src/apub/fetcher.rs b/server/src/apub/fetcher.rs
index 598903d0..0604129d 100644
--- a/server/src/apub/fetcher.rs
+++ b/server/src/apub/fetcher.rs
@@ -1,46 +1,36 @@
-use activitystreams::object::Note;
-use actix_web::client::Client;
-use diesel::{result::Error::NotFound, PgConnection};
-use log::debug;
-use serde::Deserialize;
-use std::{fmt::Debug, time::Duration};
-use url::Url;
-
use crate::{
api::site::SearchResponse,
+ apub::{is_apub_id_valid, FromApub, GroupExt, PageExt, PersonExt, APUB_JSON_CONTENT_TYPE},
blocking,
- db::{
- comment::{Comment, CommentForm},
- comment_view::CommentView,
- community::{Community, CommunityForm, CommunityModerator, CommunityModeratorForm},
- community_view::CommunityView,
- post::{Post, PostForm},
- post_view::PostView,
- user::{UserForm, User_},
- Crud,
- Joinable,
- SearchType,
- },
- naive_now,
request::{retry, RecvError},
routes::nodeinfo::{NodeInfo, NodeInfoWellKnown},
DbPool,
LemmyError,
};
-
-use crate::{
- apub::{
- get_apub_protocol_string,
- is_apub_id_valid,
- FromApub,
- GroupExt,
- PageExt,
- PersonExt,
- APUB_JSON_CONTENT_TYPE,
- },
- db::user_view::UserView,
-};
+use activitystreams::object::Note;
+use activitystreams_new::{base::BaseExt, prelude::*, primitives::XsdAnyUri};
+use actix_web::client::Client;
use chrono::NaiveDateTime;
+use diesel::{result::Error::NotFound, PgConnection};
+use lemmy_db::{
+ comment::{Comment, CommentForm},
+ comment_view::CommentView,
+ community::{Community, CommunityForm, CommunityModerator, CommunityModeratorForm},
+ community_view::CommunityView,
+ naive_now,
+ post::{Post, PostForm},
+ post_view::PostView,
+ user::{UserForm, User_},
+ user_view::UserView,
+ Crud,
+ Joinable,
+ SearchType,
+};
+use lemmy_utils::get_apub_protocol_string;
+use log::debug;
+use serde::Deserialize;
+use std::{fmt::Debug, time::Duration};
+use url::Url;
static ACTOR_REFETCH_INTERVAL_SECONDS: i64 = 24 * 60 * 60;
@@ -149,7 +139,7 @@ pub async fn search_by_apub_id(
let response = match fetch_remote_object::<SearchAcceptedObjects>(client, &query_url).await? {
SearchAcceptedObjects::Person(p) => {
- let user_uri = p.inner.object_props.get_id().unwrap().to_string();
+ let user_uri = p.inner.id().unwrap().to_string();
let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?;
@@ -158,7 +148,7 @@ pub async fn search_by_apub_id(
response
}
SearchAcceptedObjects::Group(g) => {
- let community_uri = g.inner.object_props.get_id().unwrap().to_string();
+ let community_uri = g.inner.id().unwrap().to_string();
let community =
get_or_fetch_and_upsert_remote_community(&community_uri, client, pool).await?;
@@ -174,15 +164,15 @@ pub async fn search_by_apub_id(
response
}
- SearchAcceptedObjects::Page(p) => {
- let post_form = PostForm::from_apub(&p, client, pool).await?;
+ SearchAcceptedObjects::Page(mut p) => {
+ let post_form = PostForm::from_apub(&mut p, client, pool).await?;
let p = blocking(pool, move |conn| upsert_post(&post_form, conn)).await??;
response.posts = vec![blocking(pool, move |conn| PostView::read(conn, p.id, None)).await??];
response
}
- SearchAcceptedObjects::Comment(c) => {
+ SearchAcceptedObjects::Comment(mut c) => {
let post_url = c
.object_props
.get_many_in_reply_to_xsd_any_uris()
@@ -192,9 +182,9 @@ pub async fn search_by_apub_id(
.to_string();
// TODO: also fetch parent comments if any
- let post = fetch_remote_object(client, &Url::parse(&post_url)?).await?;
- let post_form = PostForm::from_apub(&post, client, pool).await?;
- let comment_form = CommentForm::from_apub(&c, client, pool).await?;
+ let mut post = fetch_remote_object(client, &Url::parse(&post_url)?).await?;
+ let post_form = PostForm::from_apub(&mut post, client, pool).await?;
+ let comment_form = CommentForm::from_apub(&mut c, client, pool).await?;
blocking(pool, move |conn| upsert_post(&post_form, conn)).await??;
let c = blocking(pool, move |conn| upsert_comment(&comment_form, conn)).await??;
@@ -224,9 +214,9 @@ pub async fn get_or_fetch_and_upsert_remote_user(
// If its older than a day, re-fetch it
Ok(u) if !u.local && should_refetch_actor(u.last_refreshed_at) => {
debug!("Fetching and updating from remote user: {}", apub_id);
- let person = fetch_remote_object::<PersonExt>(client, &Url::parse(apub_id)?).await?;
+ let mut person = fetch_remote_object::<PersonExt>(client, &Url::parse(apub_id)?).await?;
- let mut uf = UserForm::from_apub(&person, client, pool).await?;
+ let mut uf = UserForm::from_apub(&mut person, client, pool).await?;
uf.last_refreshed_at = Some(naive_now());
let user = blocking(pool, move |conn| User_::update(conn, u.id, &uf)).await??;
@@ -235,9 +225,9 @@ pub async fn get_or_fetch_and_upsert_remote_user(
Ok(u) => Ok(u),
Err(NotFound {}) => {
debug!("Fetching and creating remote user: {}", apub_id);
- let person = fetch_remote_object::<PersonExt>(client, &Url::parse(apub_id)?).await?;
+ let mut person = fetch_remote_object::<PersonExt>(client, &Url::parse(apub_id)?).await?;
- let uf = UserForm::from_apub(&person, client, pool).await?;
+ let uf = UserForm::from_apub(&mut person, client, pool).await?;
let user = blocking(pool, move |conn| User_::create(conn, &uf)).await??;
Ok(user)
@@ -275,9 +265,9 @@ pub async fn get_or_fetch_and_upsert_remote_community(
match community {
Ok(c) if !c.local && should_refetch_actor(c.last_refreshed_at) => {
debug!("Fetching and updating from remote community: {}", apub_id);
- let group = fetch_remote_object::<GroupExt>(client, &Url::parse(apub_id)?).await?;
+ let mut group = fetch_remote_object::<GroupExt>(client, &Url::parse(apub_id)?).await?;
- let mut cf = CommunityForm::from_apub(&group, client, pool).await?;
+ let mut cf = CommunityForm::from_apub(&mut group, client, pool).await?;
cf.last_refreshed_at = Some(naive_now());
let community = blocking(pool, move |conn| Community::update(conn, c.id, &cf)).await??;
@@ -286,17 +276,19 @@ pub async fn get_or_fetch_and_upsert_remote_community(
Ok(c) => Ok(c),
Err(NotFound {}) => {
debug!("Fetching and creating remote community: {}", apub_id);
- let group = fetch_remote_object::<GroupExt>(client, &Url::parse(apub_id)?).await?;
+ let mut group = fetch_remote_object::<GroupExt>(client, &Url::parse(apub_id)?).await?;
- let cf = CommunityForm::from_apub(&group, client, pool).await?;
+ let cf = CommunityForm::from_apub(&mut group, client, pool).await?;
let community = blocking(pool, move |conn| Community::create(conn, &cf)).await??;
// Also add the community moderators too
- let creator_and_moderator_uris = group
- .inner
- .object_props
- .get_many_attributed_to_xsd_any_uris()
- .unwrap();
+ let attributed_to = group.inner.take_attributed_to().unwrap();
+ let creator_and_moderator_uris: Vec<&XsdAnyUri> = attributed_to
+ .as_many()
+ .unwrap()
+ .iter()
+ .map(|a| a.as_xsd_any_uri().unwrap())
+ .collect();
let mut creator_and_moderators = Vec::new();
@@ -350,8 +342,8 @@ pub async fn get_or_fetch_and_insert_remote_post(
Ok(p) => Ok(p),
Err(NotFound {}) => {
debug!("Fetching and creating remote post: {}", post_ap_id);
- let post = fetch_remote_object::<PageExt>(client, &Url::parse(post_ap_id)?).await?;
- let post_form = PostForm::from_apub(&post, client, pool).await?;
+ let mut post = fetch_remote_object::<PageExt>(client, &Url::parse(post_ap_id)?).await?;
+ let post_form = PostForm::from_apub(&mut post, client, pool).await?;
let post = blocking(pool, move |conn| Post::create(conn, &post_form)).await??;
@@ -388,8 +380,8 @@ pub async fn get_or_fetch_and_insert_remote_comment(
"Fetching and creating remote comment and its parents: {}",
comment_ap_id
);
- let comment = fetch_remote_object::<Note>(client, &Url::parse(comment_ap_id)?).await?;
- let comment_form = CommentForm::from_apub(&comment, client, pool).await?;
+ let mut comment = fetch_remote_object::<Note>(client, &Url::parse(comment_ap_id)?).await?;
+ let comment_form = CommentForm::from_apub(&mut comment, client, pool).await?;
let comment = blocking(pool, move |conn| Comment::create(conn, &comment_form)).await??;
diff --git a/server/src/apub/mod.rs b/server/src/apub/mod.rs
index 90df8734..eeac5fec 100644
--- a/server/src/apub/mod.rs
+++ b/server/src/apub/mod.rs
@@ -16,41 +16,35 @@ use crate::{
page_extension::PageExtension,
signatures::{PublicKey, PublicKeyExtension},
},
- convert_datetime,
- db::user::User_,
+ blocking,
request::{retry, RecvError},
routes::webfinger::WebFingerResponse,
DbPool,
LemmyError,
- MentionData,
- Settings,
};
-use activitystreams::{
- actor::{properties::ApActorProperties, Group, Person},
- object::Page,
+use activitystreams::object::Page;
+use activitystreams_ext::{Ext1, Ext2};
+use activitystreams_new::{
+ activity::Follow,
+ actor::{ApActor, Group, Person},
+ object::Tombstone,
+ prelude::*,
};
-use activitystreams_ext::{Ext1, Ext2, Ext3};
-use activitystreams_new::{activity::Follow, object::Tombstone, prelude::*};
use actix_web::{body::Body, client::Client, HttpResponse};
use chrono::NaiveDateTime;
+use failure::_core::fmt::Debug;
+use lemmy_db::{activity::do_insert_activity, user::User_};
+use lemmy_utils::{convert_datetime, get_apub_protocol_string, settings::Settings, MentionData};
use log::debug;
use serde::Serialize;
use url::Url;
-type GroupExt = Ext3<Group, GroupExtension, ApActorProperties, PublicKeyExtension>;
-type PersonExt = Ext2<Person, ApActorProperties, PublicKeyExtension>;
+type GroupExt = Ext2<ApActor<Group>, GroupExtension, PublicKeyExtension>;
+type PersonExt = Ext1<ApActor<Person>, PublicKeyExtension>;
type PageExt = Ext1<Page, PageExtension>;
pub static APUB_JSON_CONTENT_TYPE: &str = "application/activity+json";
-pub enum EndpointType {
- Community,
- User,
- Post,
- Comment,
- PrivateMessage,
-}
-
/// Convert the data to json and turn it into an HTTP Response with the correct ActivityPub
/// headers.
fn create_apub_response<T>(data: &T) -> HttpResponse<Body>
@@ -71,34 +65,6 @@ where
.json(data)
}
-/// Generates the ActivityPub ID for a given object type and ID.
-pub fn make_apub_endpoint(endpoint_type: EndpointType, name: &str) -> Url {
- let point = match endpoint_type {
- EndpointType::Community => "c",
- EndpointType::User => "u",
- EndpointType::Post => "post",
- EndpointType::Comment => "comment",
- EndpointType::PrivateMessage => "private_message",
- };
-
- Url::parse(&format!(
- "{}://{}/{}/{}",
- get_apub_protocol_string(),
- Settings::get().hostname,
- point,
- name
- ))
- .unwrap()
-}
-
-pub fn get_apub_protocol_string() -> &'static str {
- if Settings::get().federation.tls_enabled {
- "https"
- } else {
- "http"
- }
-}
-
// Checks if the ID has a valid format, correct scheme, and is in the allowed instance list.
fn is_apub_id_valid(apub_id: &Url) -> bool {
debug!("Checking {}", apub_id);
@@ -163,7 +129,7 @@ fn create_tombstone(
pub trait FromApub {
type ApubType;
async fn from_apub(
- apub: &Self::ApubType,
+ apub: &mut Self::ApubType,
client: &Client,
pool: &DbPool,
) -> Result<Self, LemmyError>
@@ -372,3 +338,19 @@ pub async fn fetch_webfinger_url(
.to_owned()
.ok_or_else(|| format_err!("No href found.").into())
}
+
+pub async fn insert_activity<T>(
+ user_id: i32,
+ data: T,
+ local: bool,
+ pool: &DbPool,
+) -> Result<(), LemmyError>
+where
+ T: Serialize + Debug + Send + 'static,
+{
+ blocking(pool, move |conn| {
+ do_insert_activity(conn, user_id, &data, local)
+ })
+ .await??;
+ Ok(())
+}
diff --git a/server/src/apub/post.rs b/server/src/apub/post.rs
index 60cb0b55..ba0372c4 100644
--- a/server/src/apub/post.rs
+++ b/server/src/apub/post.rs
@@ -6,7 +6,6 @@ use crate::{
create_tombstone,
extensions::page_extension::PageExtension,
fetcher::{get_or_fetch_and_upsert_remote_community, get_or_fetch_and_upsert_remote_user},
- get_apub_protocol_string,
ActorType,
ApubLikeableType,
ApubObjectType,
@@ -15,17 +14,9 @@ use crate::{
ToApub,
},
blocking,
- convert_datetime,
- db::{
- community::Community,
- post::{Post, PostForm},
- user::User_,
- Crud,
- },
routes::DbPoolParam,
DbPool,
LemmyError,
- Settings,
};
use activitystreams::{
activity::{Create, Delete, Dislike, Like, Remove, Undo, Update},
@@ -36,6 +27,13 @@ use activitystreams::{
use activitystreams_ext::Ext1;
use activitystreams_new::object::Tombstone;
use actix_web::{body::Body, client::Client, web, HttpResponse};
+use lemmy_db::{
+ community::Community,
+ post::{Post, PostForm},
+ user::User_,
+ Crud,
+};
+use lemmy_utils::{convert_datetime, get_apub_protocol_string, settings::Settings};
use serde::Deserialize;
#[derive(Deserialize)]
@@ -164,7 +162,7 @@ impl FromApub for PostForm {
/// Parse an ActivityPub page received from another instance into a Lemmy post.
async fn from_apub(
- page: &PageExt,
+ page: &mut PageExt,
client: &Client,
pool: &DbPool,
) -> Result<PostForm, LemmyError> {
diff --git a/server/src/apub/private_message.rs b/server/src/apub/private_message.rs
index ae4c3626..567a6178 100644
--- a/server/src/apub/private_message.rs
+++ b/server/src/apub/private_message.rs
@@ -3,18 +3,12 @@ use crate::{
activities::send_activity,
create_tombstone,
fetcher::get_or_fetch_and_upsert_remote_user,
+ insert_activity,
ApubObjectType,
FromApub,
ToApub,
},
blocking,
- convert_datetime,
- db::{
- activity::insert_activity,
- private_message::{PrivateMessage, PrivateMessageForm},
- user::User_,
- Crud,
- },
DbPool,
LemmyError,
};
@@ -25,6 +19,12 @@ use activitystreams::{
};
use activitystreams_new::object::Tombstone;
use actix_web::client::Client;
+use lemmy_db::{
+ private_message::{PrivateMessage, PrivateMessageForm},
+ user::User_,
+ Crud,
+};
+use lemmy_utils::convert_datetime;
#[async_trait::async_trait(?Send)]
impl ToApub for PrivateMessage {
@@ -71,7 +71,7 @@ impl FromApub for PrivateMessageForm {
/// Parse an ActivityPub note received from another instance into a Lemmy Private message
async fn from_apub(
- note: &Note,
+ note: &mut Note,
client: &Client,
pool: &DbPool,
) -> Result<PrivateMessageForm, LemmyError> {
diff --git a/server/src/apub/shared_inbox.rs b/server/src/apub/shared_inbox.rs
index 66773252..75ce3415 100644
--- a/server/src/apub/shared_inbox.rs
+++ b/server/src/apub/shared_inbox.rs
@@ -5,6 +5,7 @@ use crate::{
post::PostResponse,
},
apub::{
+ community::do_announce,
extensions::signatures::verify,
fetcher::{
get_or_fetch_and_insert_remote_comment,
@@ -12,25 +13,13 @@ use crate::{
get_or_fetch_and_upsert_remote_community,
get_or_fetch_and_upsert_remote_user,
},
+ insert_activity,
FromApub,
GroupExt,
PageExt,
},
blocking,
- db::{
- activity::insert_activity,
- comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
- comment_view::CommentView,
- community::{Community, CommunityForm},
- community_view::CommunityView,
- post::{Post, PostForm, PostLike, PostLikeForm},
- post_view::PostView,
- Crud,
- Likeable,
- },
- naive_now,
routes::{ChatServerParam, DbPoolParam},
- scrape_text_for_mentions,
websocket::{
server::{Sen