almost everything working

This commit is contained in:
Felix Ableitner 2023-03-14 22:26:56 +01:00
parent b83640ae60
commit 471f113dbe
4 changed files with 57 additions and 31 deletions

View file

@ -56,7 +56,9 @@ where
let actor_id = activity.actor(); let actor_id = activity.actor();
let activity_id = activity.id(); let activity_id = activity.id();
let activity_serialized = serde_json::to_string_pretty(&activity)?; let activity_serialized = serde_json::to_string_pretty(&activity)?;
let private_key = actor.private_key_pem().unwrap(); let private_key = actor
.private_key_pem()
.expect("Actor for sending activity has private key");
let inboxes: Vec<Url> = inboxes let inboxes: Vec<Url> = inboxes
.into_iter() .into_iter()
.unique() .unique()

View file

@ -1,4 +1,4 @@
use crate::{error::Error, traits::ApubCollection}; use crate::{config::Data, error::Error, fetch::fetch_object_http, traits::ApubCollection};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{ use std::{
fmt::{Debug, Display, Formatter}, fmt::{Debug, Display, Formatter},
@ -6,16 +6,19 @@ use std::{
}; };
use url::Url; use url::Url;
/// TODO: implement and document this, update trait docs /// Typed wrapper for Activitypub Collection ID which helps with dereferencing.
/// TODO: which handlers need to receive owner, and should it be simply an url or what?
/// TODO: current trait impl without read_from_apub_id() method wont work for http handlers
/// -> maybe remove method into_apub() and instead add read_local() (reads from db and
/// directly returns serialized collection)
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(transparent)] #[serde(transparent)]
pub struct CollectionId<Kind>(Box<Url>, PhantomData<Kind>); pub struct CollectionId<Kind>(Box<Url>, PhantomData<Kind>)
where
Kind: ApubCollection,
for<'de2> <Kind as ApubCollection>::ApubType: Deserialize<'de2>;
impl<Kind> CollectionId<Kind> { impl<Kind> CollectionId<Kind>
where
Kind: ApubCollection,
for<'de2> <Kind as ApubCollection>::ApubType: Deserialize<'de2>,
{
/// Construct a new CollectionId instance /// Construct a new CollectionId instance
pub fn parse<T>(url: T) -> Result<Self, url::ParseError> pub fn parse<T>(url: T) -> Result<Self, url::ParseError>
where where
@ -25,14 +28,30 @@ impl<Kind> CollectionId<Kind> {
Ok(Self(Box::new(url.try_into()?), PhantomData::<Kind>)) Ok(Self(Box::new(url.try_into()?), PhantomData::<Kind>))
} }
/// TODO /// Fetches collection over HTTP
pub async fn dereference<T>(&self, _: T) -> Result<Kind, Error> { ///
todo!() /// Unlike [ObjectId::fetch](crate::fetch::object_id::ObjectId::fetch) this method doesn't do
/// any caching.
pub async fn dereference(
&self,
owner: &<Kind as ApubCollection>::Owner,
data: &Data<<Kind as ApubCollection>::DataType>,
) -> Result<Kind, <Kind as ApubCollection>::Error>
where
<Kind as ApubCollection>::Error: From<Error>,
{
let apub = fetch_object_http(&self.0, data).await?;
Kind::verify(&apub, &self.0, data).await?;
Kind::from_apub(apub, owner, data).await
} }
} }
/// Need to implement clone manually, to avoid requiring Kind to be Clone /// Need to implement clone manually, to avoid requiring Kind to be Clone
impl<Kind> Clone for CollectionId<Kind> { impl<Kind> Clone for CollectionId<Kind>
where
Kind: ApubCollection,
for<'de2> <Kind as ApubCollection>::ApubType: serde::Deserialize<'de2>,
{
fn clone(&self) -> Self { fn clone(&self) -> Self {
CollectionId(self.0.clone(), self.1) CollectionId(self.0.clone(), self.1)
} }

View file

@ -79,3 +79,15 @@ where
self.inner.receive(data).await self.inner.receive(data).await
} }
} }
impl<T> Clone for WithContext<T>
where
T: Clone,
{
fn clone(&self) -> Self {
Self {
context: self.context.clone(),
inner: self.inner.clone(),
}
}
}

View file

@ -3,6 +3,7 @@
use crate::{config::Data, protocol::public_key::PublicKey}; use crate::{config::Data, protocol::public_key::PublicKey};
use async_trait::async_trait; use async_trait::async_trait;
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use serde::Deserialize;
use std::{fmt::Debug, ops::Deref}; use std::{fmt::Debug, ops::Deref};
use url::Url; use url::Url;
@ -151,8 +152,8 @@ pub trait ApubObject: Sized {
/// Convert object from ActivityPub type to database type. /// Convert object from ActivityPub type to database type.
/// ///
/// Called when an object is received from HTTP fetch or as part of an activity. This method /// Called when an object is received from HTTP fetch or as part of an activity. This method
/// should do verification and write the received object to database. Note that there is no /// should write the received object to database. Note that there is no distinction between
/// distinction between create and update, so an `upsert` operation should be used. /// create and update, so an `upsert` operation should be used.
async fn from_apub( async fn from_apub(
apub: Self::ApubType, apub: Self::ApubType,
data: &Data<Self::DataType>, data: &Data<Self::DataType>,
@ -252,7 +253,7 @@ pub trait Actor: ApubObject + Send + 'static {
/// Generates a public key struct for use in the actor json representation /// Generates a public key struct for use in the actor json representation
fn public_key(&self) -> PublicKey { fn public_key(&self) -> PublicKey {
PublicKey::new(self.id().clone(), self.public_key_pem().to_string()) PublicKey::new(self.id(), self.public_key_pem().to_string())
} }
/// The actor's shared inbox, if any /// The actor's shared inbox, if any
@ -301,17 +302,13 @@ pub trait ApubCollection: Sized {
/// [crate::config::FederationConfigBuilder::app_data] type. /// [crate::config::FederationConfigBuilder::app_data] type.
type DataType: Clone + Send + Sync; type DataType: Clone + Send + Sync;
/// The type of protocol struct which gets sent over network to federate this database struct. /// The type of protocol struct which gets sent over network to federate this database struct.
type ApubType; type ApubType: for<'de2> Deserialize<'de2>;
/// Error type returned by handler methods /// Error type returned by handler methods
type Error; type Error;
/// Convert database type to Activitypub type. /// Reads local collection from database and returns it as Activitypub JSON.
/// async fn read_local(
/// Called when a local object gets fetched by another instance over HTTP, or when an object owner: &Self::Owner,
/// gets sent in an activity.
async fn into_apub(
self,
owner: Self::Owner,
data: &Data<Self::DataType>, data: &Data<Self::DataType>,
) -> Result<Self::ApubType, Self::Error>; ) -> Result<Self::ApubType, Self::Error>;
@ -319,12 +316,8 @@ pub trait ApubCollection: Sized {
/// ///
/// You should check here that the domain of id matches `expected_domain`. Additionally you /// You should check here that the domain of id matches `expected_domain`. Additionally you
/// should perform any application specific checks. /// should perform any application specific checks.
///
/// It is necessary to use a separate method for this, because it might be used for activities
/// like `Delete/Note`, which shouldn't perform any database write for the inner `Note`.
async fn verify( async fn verify(
apub: &Self::ApubType, apub: &Self::ApubType,
owner: Self::Owner,
expected_domain: &Url, expected_domain: &Url,
data: &Data<Self::DataType>, data: &Data<Self::DataType>,
) -> Result<(), Self::Error>; ) -> Result<(), Self::Error>;
@ -332,11 +325,11 @@ pub trait ApubCollection: Sized {
/// Convert object from ActivityPub type to database type. /// Convert object from ActivityPub type to database type.
/// ///
/// Called when an object is received from HTTP fetch or as part of an activity. This method /// Called when an object is received from HTTP fetch or as part of an activity. This method
/// should do verification and write the received object to database. Note that there is no /// should also write the received object to database. Note that there is no distinction
/// distinction between create and update, so an `upsert` operation should be used. /// between create and update, so an `upsert` operation should be used.
async fn from_apub( async fn from_apub(
apub: Self::ApubType, apub: Self::ApubType,
owner: Self::Owner, owner: &Self::Owner,
data: &Data<Self::DataType>, data: &Data<Self::DataType>,
) -> Result<Self, Self::Error>; ) -> Result<Self, Self::Error>;
} }