Make it work with Lemmy

This commit is contained in:
Felix Ableitner 2023-03-11 16:16:09 +01:00
parent 6b3a4f8942
commit 29d040bcd3
6 changed files with 36 additions and 11 deletions

2
Cargo.lock generated
View file

@ -4,7 +4,7 @@ version = 3
[[package]]
name = "activitypub_federation"
version = "0.4.0-rc1"
version = "0.4.0-rc2"
dependencies = [
"activitystreams-kinds",
"actix-rt",

View file

@ -7,7 +7,7 @@ use crate::{
error::Error,
http_signatures::sign_request,
reqwest_shim::ResponseExt,
traits::ActivityHandler,
traits::{ActivityHandler, Actor},
APUB_JSON_CONTENT_TYPE,
};
use anyhow::anyhow;
@ -40,9 +40,9 @@ use url::Url;
/// signature. Generated with [crate::http_signatures::generate_actor_keypair].
/// - `inboxes`: List of actor inboxes that should receive the activity. Should be built by calling
/// [crate::traits::Actor::shared_inbox_or_inbox] for each target actor.
pub async fn send_activity<Activity, Datatype>(
pub async fn send_activity<Activity, Datatype, ActorType>(
activity: Activity,
private_key: String,
actor: ActorType,
inboxes: Vec<Url>,
data: &RequestData<Datatype>,
) -> Result<(), <Activity as ActivityHandler>::Error>
@ -50,11 +50,14 @@ where
Activity: ActivityHandler + Serialize,
<Activity as ActivityHandler>::Error: From<anyhow::Error> + From<serde_json::Error>,
Datatype: Clone,
ActorType: Actor,
for<'de2> ActorType::ApubType: Deserialize<'de2>,
{
let config = &data.config;
let actor_id = activity.actor();
let activity_id = activity.id();
let activity_serialized = serde_json::to_string_pretty(&activity)?;
let private_key = actor.private_key_pem().unwrap();
let inboxes: Vec<Url> = inboxes
.into_iter()
.unique()

View file

@ -112,8 +112,8 @@ mod test {
let request_builder =
ClientWithMiddleware::from(Client::default()).post("https://example.com/inbox");
let activity = Follow {
actor: ObjectId::new("http://localhost:123").unwrap(),
object: ObjectId::new("http://localhost:124").unwrap(),
actor: ObjectId::parse("http://localhost:123").unwrap(),
object: ObjectId::parse("http://localhost:124").unwrap(),
kind: Default::default(),
id: "http://localhost:123/1".try_into().unwrap(),
};

View file

@ -5,9 +5,21 @@ use serde::{Deserialize, Serialize};
use std::{
fmt::{Debug, Display, Formatter},
marker::PhantomData,
str::FromStr,
};
use url::Url;
impl<T> FromStr for ObjectId<T>
where
T: ApubObject + Send + 'static,
for<'de2> <T as ApubObject>::ApubType: Deserialize<'de2>,
{
type Err = url::ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
ObjectId::parse(s)
}
}
/// Typed wrapper for Activitypub Object ID which helps with dereferencing and caching.
///
/// It provides convenient methods for fetching the object from remote server or local database.
@ -32,7 +44,7 @@ use url::Url;
/// .app_data(db_connection)
/// .build()?;
/// let request_data = config.to_request_data();
/// let object_id = ObjectId::<DbUser>::new("https://lemmy.ml/u/nutomic")?;
/// let object_id = ObjectId::<DbUser>::parse("https://lemmy.ml/u/nutomic")?;
/// // Attempt to fetch object from local database or fall back to remote server
/// let user = object_id.dereference(&request_data).await;
/// assert!(user.is_ok());
@ -55,7 +67,7 @@ where
for<'de2> <Kind as ApubObject>::ApubType: serde::Deserialize<'de2>,
{
/// Construct a new objectid instance
pub fn new<T>(url: T) -> Result<Self, url::ParseError>
pub fn parse<T>(url: T) -> Result<Self, url::ParseError>
where
T: TryInto<Url>,
url::ParseError: From<<T as TryInto<Url>>::Error>,
@ -238,7 +250,7 @@ pub mod tests {
#[test]
fn test_deserialize() {
let id = ObjectId::<DbUser>::new("http://test.com/").unwrap();
let id = ObjectId::<DbUser>::parse("http://test.com/").unwrap();
let string = serde_json::to_string(&id).unwrap();
assert_eq!("\"http://test.com/\"", string);

View file

@ -21,7 +21,7 @@ impl PublicKey {
/// Create a new [PublicKey] struct for the `owner` with `public_key_pem`.
///
/// It uses an standard key id of `{actor_id}#main-key`
pub fn new(owner: Url, public_key_pem: String) -> Self {
pub(crate) fn new(owner: Url, public_key_pem: String) -> Self {
let id = main_key_id(&owner);
PublicKey {
id,

View file

@ -227,7 +227,7 @@ pub trait ActivityHandler {
}
/// Trait to allow retrieving common Actor data.
pub trait Actor: ApubObject {
pub trait Actor: ApubObject + Send + 'static {
/// `id` field of the actor
fn id(&self) -> &Url;
@ -237,6 +237,12 @@ pub trait Actor: ApubObject {
/// actor keypair.
fn public_key_pem(&self) -> &str;
/// The actor's private key for signing outgoing activities.
///
/// Use [generate_actor_keypair](crate::http_signatures::generate_actor_keypair) to create the
/// actor keypair.
fn private_key_pem(&self) -> Option<String>;
/// The inbox where activities for this user should be sent to
fn inbox(&self) -> Url;
@ -412,6 +418,10 @@ pub mod tests {
&self.public_key
}
fn private_key_pem(&self) -> Option<String> {
self.private_key.clone()
}
fn inbox(&self) -> Url {
self.inbox.clone()
}