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 activity_id = activity.id();
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
.into_iter()
.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 std::{
fmt::{Debug, Display, Formatter},
@ -6,16 +6,19 @@ use std::{
};
use url::Url;
/// TODO: implement and document this, update trait docs
/// 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)
/// Typed wrapper for Activitypub Collection ID which helps with dereferencing.
#[derive(Serialize, Deserialize)]
#[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
pub fn parse<T>(url: T) -> Result<Self, url::ParseError>
where
@ -25,14 +28,30 @@ impl<Kind> CollectionId<Kind> {
Ok(Self(Box::new(url.try_into()?), PhantomData::<Kind>))
}
/// TODO
pub async fn dereference<T>(&self, _: T) -> Result<Kind, Error> {
todo!()
/// Fetches collection over HTTP
///
/// 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
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 {
CollectionId(self.0.clone(), self.1)
}

View file

@ -79,3 +79,15 @@ where
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 async_trait::async_trait;
use chrono::NaiveDateTime;
use serde::Deserialize;
use std::{fmt::Debug, ops::Deref};
use url::Url;
@ -151,8 +152,8 @@ pub trait ApubObject: Sized {
/// 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
/// should do verification and write the received object to database. Note that there is no
/// distinction between create and update, so an `upsert` operation should be used.
/// should write the received object to database. Note that there is no distinction between
/// create and update, so an `upsert` operation should be used.
async fn from_apub(
apub: Self::ApubType,
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
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
@ -301,17 +302,13 @@ pub trait ApubCollection: Sized {
/// [crate::config::FederationConfigBuilder::app_data] type.
type DataType: Clone + Send + Sync;
/// 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
type Error;
/// Convert database type to Activitypub type.
///
/// Called when a local object gets fetched by another instance over HTTP, or when an object
/// gets sent in an activity.
async fn into_apub(
self,
owner: Self::Owner,
/// Reads local collection from database and returns it as Activitypub JSON.
async fn read_local(
owner: &Self::Owner,
data: &Data<Self::DataType>,
) -> 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
/// 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(
apub: &Self::ApubType,
owner: Self::Owner,
expected_domain: &Url,
data: &Data<Self::DataType>,
) -> Result<(), Self::Error>;
@ -332,11 +325,11 @@ pub trait ApubCollection: Sized {
/// 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
/// should do verification and write the received object to database. Note that there is no
/// distinction between create and update, so an `upsert` operation should be used.
/// should also write the received object to database. Note that there is no distinction
/// between create and update, so an `upsert` operation should be used.
async fn from_apub(
apub: Self::ApubType,
owner: Self::Owner,
owner: &Self::Owner,
data: &Data<Self::DataType>,
) -> Result<Self, Self::Error>;
}