Compare commits
1 commit
main
...
asonix/gat
Author | SHA1 | Date | |
---|---|---|---|
Aode (lion) | d1d2743dfd |
|
@ -1,3 +1,5 @@
|
|||
#![feature(generic_associated_types)]
|
||||
|
||||
use actix_web::{
|
||||
error::BlockingError,
|
||||
web::{self, ServiceConfig},
|
||||
|
@ -47,18 +49,13 @@ pub trait Verifier {
|
|||
type Verify: Verify<Error = Self::VerifyError> + VerifyBuilder;
|
||||
}
|
||||
|
||||
pub trait RepoFactoryX<D: Dereference> {
|
||||
pub trait RepoFactory {
|
||||
type RepoError;
|
||||
type RepoFactory: for<'a> RepoFactory<'a, D, RepoError = Self::RepoError>;
|
||||
type Repo<'a>: Repo<Error = Self::RepoError> + 'a
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn factory(&self) -> &Self::RepoFactory;
|
||||
}
|
||||
|
||||
pub trait RepoFactory<'a, D: Dereference> {
|
||||
type RepoError;
|
||||
type Repo: for<'b> Repo<'b, D, Error = Self::RepoError> + 'a;
|
||||
|
||||
fn repo(&'a self) -> Self::Repo;
|
||||
fn repo<'a>(&'a self) -> Self::Repo<'a>;
|
||||
}
|
||||
|
||||
/// Ingest activitypub objects at a given endpoint
|
||||
|
@ -90,10 +87,10 @@ where
|
|||
Activity: for<'de> serde::de::Deserialize<'de> + 'static,
|
||||
Metadata: FromRequest + 'static,
|
||||
I: for<'a> Ingest<'a, Activity, Metadata> + 'static,
|
||||
V: RepoFactoryX<ObjectId<PublicKeyType>> + Verifier + DigestFactory + Clone + 'static,
|
||||
V: RepoFactory + Verifier + DigestFactory + Clone + 'static,
|
||||
<V as DigestFactory>::Digest: Clone,
|
||||
E: ResponseError + From<VerifyError> + From<V::VerifyError> + 'static,
|
||||
E: From<<V as RepoFactoryX<ObjectId<PublicKeyType>>>::RepoError>,
|
||||
E: From<<V as RepoFactory>::RepoError>,
|
||||
{
|
||||
move |service_config: &mut ServiceConfig| {
|
||||
let signature = VerifySignature::new(
|
||||
|
@ -148,14 +145,14 @@ pub fn serve_objects<D, R, V, E>(
|
|||
require_signature: bool,
|
||||
) -> impl FnOnce(&mut ServiceConfig)
|
||||
where
|
||||
D: Dereference + From<Url> + 'static,
|
||||
D: Dereference + From<Url> + Send + Sync + 'static,
|
||||
<D as Dereference>::Output: serde::ser::Serialize,
|
||||
R: for<'a> RepoFactory<'a, D> + 'static,
|
||||
V: RepoFactoryX<ObjectId<PublicKeyType>> + Verifier + Clone + 'static,
|
||||
R: RepoFactory + 'static,
|
||||
V: RepoFactory + Verifier + Clone + 'static,
|
||||
E: ResponseError
|
||||
+ From<VerifyError>
|
||||
+ From<V::VerifyError>
|
||||
+ From<<V as RepoFactoryX<ObjectId<PublicKeyType>>>::RepoError>
|
||||
+ From<<V as RepoFactory>::RepoError>
|
||||
+ 'static,
|
||||
{
|
||||
move |service_config: &mut ServiceConfig| {
|
||||
|
@ -212,9 +209,9 @@ async fn serve_object_handler<D, R>(
|
|||
serve_info: web::Data<ServeInfo<R>>,
|
||||
) -> HttpResponse
|
||||
where
|
||||
D: Dereference + From<Url> + 'static,
|
||||
D: Dereference + From<Url> + Send + Sync + 'static,
|
||||
<D as Dereference>::Output: serde::ser::Serialize,
|
||||
R: for<'a> RepoFactory<'a, D> + 'static,
|
||||
R: RepoFactory + 'static,
|
||||
{
|
||||
let uri = req.uri().to_string();
|
||||
let url = format!("{}{}", serve_info.local_host, uri);
|
||||
|
@ -225,7 +222,7 @@ where
|
|||
|
||||
let d = D::from(url);
|
||||
let repo = serve_info.repo_factory.repo();
|
||||
let res = repo.fetch(&d).await;
|
||||
let res = repo.fetch(d).await;
|
||||
|
||||
match res {
|
||||
Ok(Some(object)) => HttpResponse::Ok()
|
||||
|
@ -363,7 +360,7 @@ async fn verify<'a, V, E>(
|
|||
signing_string: String,
|
||||
) -> Result<bool, E>
|
||||
where
|
||||
V: Verifier + RepoFactoryX<ObjectId<PublicKeyType>>,
|
||||
V: Verifier + RepoFactory,
|
||||
E: From<VerifyError> + From<V::RepoError> + From<V::VerifyError> + 'static,
|
||||
{
|
||||
match algorithm {
|
||||
|
@ -373,11 +370,14 @@ where
|
|||
Some(other) => return Err(VerifyError::Algorithm(other.to_string()).into()),
|
||||
};
|
||||
|
||||
let key_id = object_id(key_id.parse().map_err(|_| VerifyError::KeyId(key_id))?);
|
||||
let key_id = match key_id.parse() {
|
||||
Ok(url) => object_id(url),
|
||||
Err(_) => return Err(VerifyError::KeyId(key_id).into()),
|
||||
};
|
||||
|
||||
let repo = verifier.factory().repo();
|
||||
let repo = verifier.repo();
|
||||
let response = repo
|
||||
.fetch(&key_id)
|
||||
.fetch(key_id.clone())
|
||||
.await
|
||||
.map_err(E::from)?
|
||||
.ok_or(VerifyError::KeyNotFound)?;
|
||||
|
@ -409,11 +409,11 @@ where
|
|||
|
||||
impl<V, E> SignatureVerify for VerifyMiddleware<V, ObjectId<PublicKeyType>, E>
|
||||
where
|
||||
V: RepoFactoryX<ObjectId<PublicKeyType>> + Verifier + Clone + 'static,
|
||||
V: RepoFactory + Verifier + Clone + 'static,
|
||||
E: ResponseError
|
||||
+ From<VerifyError>
|
||||
+ From<V::VerifyError>
|
||||
+ From<<V as RepoFactoryX<ObjectId<PublicKeyType>>>::RepoError>
|
||||
+ From<<V as RepoFactory>::RepoError>
|
||||
+ 'static,
|
||||
{
|
||||
type Error = E;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(generic_associated_types)]
|
||||
|
||||
use actix_http::error::BlockingError;
|
||||
use apub_core::{
|
||||
deref::{Dereference, Repo},
|
||||
|
@ -100,7 +102,7 @@ where
|
|||
|
||||
async fn do_fetch<Id: Dereference>(
|
||||
&self,
|
||||
id: &Id,
|
||||
id: Id,
|
||||
) -> Result<Option<<Id as Dereference>::Output>, AwcError<SignError<Crypto>>> {
|
||||
let mut response = self
|
||||
.client
|
||||
|
@ -121,21 +123,23 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, Id, CurrentSession, Crypto> Repo<'a, Id> for AwcClient<'a, CurrentSession, Crypto>
|
||||
impl<'b, CurrentSession, Crypto> Repo for AwcClient<'b, CurrentSession, Crypto>
|
||||
where
|
||||
Id: Dereference + 'a,
|
||||
CurrentSession: Session,
|
||||
Crypto: SignFactory,
|
||||
{
|
||||
type Error = AwcError<SignError<Crypto>>;
|
||||
type Future = Pin<
|
||||
Box<dyn Future<Output = Result<Option<<Id as Dereference>::Output>, Self::Error>> + 'a>,
|
||||
>;
|
||||
type Future<'a, Id: Dereference + 'a>
|
||||
where
|
||||
'b: 'a,
|
||||
Self: 'a,
|
||||
= Pin<Box<dyn Future<Output = Result<Option<Id::Output>, Self::Error>> + 'a>>;
|
||||
|
||||
fn fetch(&'a self, id: &'a Id) -> Self::Future {
|
||||
fn fetch<'a, Id: Dereference + 'a>(&'a self, id: Id) -> Self::Future<'a, Id> {
|
||||
let url = id.url().clone();
|
||||
Box::pin(apub_core::session::guard(
|
||||
self.do_fetch(id),
|
||||
id.url(),
|
||||
url,
|
||||
&self.session,
|
||||
))
|
||||
}
|
||||
|
@ -188,7 +192,7 @@ where
|
|||
|
||||
Ok(())
|
||||
},
|
||||
inbox,
|
||||
inbox.clone(),
|
||||
&self.session,
|
||||
))
|
||||
}
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
use std::{future::Future, rc::Rc, sync::Arc};
|
||||
use url::Url;
|
||||
|
||||
pub trait Repo<'a, D: Dereference> {
|
||||
pub trait Repo {
|
||||
type Error: std::error::Error + 'static;
|
||||
type Future: Future<Output = Result<Option<D::Output>, Self::Error>> + 'a;
|
||||
type Future<'a, Id: Dereference + 'a>: Future<Output = Result<Option<Id::Output>, Self::Error>>
|
||||
+ 'a
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn fetch(&'a self, id: &'a D) -> Self::Future;
|
||||
fn fetch<'a, Id: Dereference + 'a>(&'a self, id: Id) -> Self::Future<'a, Id>;
|
||||
}
|
||||
|
||||
pub trait Dereference {
|
||||
pub trait Dereference: Clone + Send + Sync {
|
||||
type Output: serde::de::DeserializeOwned;
|
||||
|
||||
fn url(&self) -> &Url;
|
||||
|
@ -25,17 +28,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Dereference for &'a mut T
|
||||
where
|
||||
T: Dereference,
|
||||
{
|
||||
type Output = T::Output;
|
||||
|
||||
fn url(&self) -> &Url {
|
||||
T::url(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Dereference for Box<T>
|
||||
where
|
||||
T: Dereference,
|
||||
|
@ -47,17 +39,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> Dereference for Rc<T>
|
||||
where
|
||||
T: Dereference,
|
||||
{
|
||||
type Output = T::Output;
|
||||
|
||||
fn url(&self) -> &Url {
|
||||
T::url(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Dereference for Arc<T>
|
||||
where
|
||||
T: Dereference,
|
||||
|
@ -69,62 +50,79 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, D: Dereference, T> Repo<'a, D> for &'b T
|
||||
impl<'b, T> Repo for &'b T
|
||||
where
|
||||
T: Repo<'a, D>,
|
||||
T: Repo,
|
||||
{
|
||||
type Error = T::Error;
|
||||
type Future = T::Future;
|
||||
type Future<'a, Id: Dereference + 'a>
|
||||
where
|
||||
'b: 'a,
|
||||
T: 'a,
|
||||
= T::Future<'a, Id>;
|
||||
|
||||
fn fetch(&'a self, id: &'a D) -> Self::Future {
|
||||
fn fetch<'a, Id: Dereference + 'a>(&'a self, id: Id) -> Self::Future<'a, Id> {
|
||||
T::fetch(self, id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, D: Dereference, T> Repo<'a, D> for &'b mut T
|
||||
impl<'b, T> Repo for &'b mut T
|
||||
where
|
||||
T: Repo<'a, D>,
|
||||
T: Repo,
|
||||
{
|
||||
type Error = T::Error;
|
||||
type Future = T::Future;
|
||||
type Future<'a, Id: Dereference + 'a>
|
||||
where
|
||||
'b: 'a,
|
||||
T: 'a,
|
||||
= T::Future<'a, Id>;
|
||||
|
||||
fn fetch(&'a self, id: &'a D) -> Self::Future {
|
||||
fn fetch<'a, Id: Dereference + 'a>(&'a self, id: Id) -> Self::Future<'a, Id> {
|
||||
T::fetch(self, id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, D: Dereference, T> Repo<'a, D> for Box<T>
|
||||
impl<T> Repo for Box<T>
|
||||
where
|
||||
T: Repo<'a, D>,
|
||||
T: Repo,
|
||||
{
|
||||
type Error = T::Error;
|
||||
type Future = T::Future;
|
||||
type Future<'a, Id: Dereference + 'a>
|
||||
where
|
||||
T: 'a,
|
||||
= T::Future<'a, Id>;
|
||||
|
||||
fn fetch(&'a self, id: &'a D) -> Self::Future {
|
||||
fn fetch<'a, Id: Dereference + 'a>(&'a self, id: Id) -> Self::Future<'a, Id> {
|
||||
T::fetch(self, id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, D: Dereference, T> Repo<'a, D> for Rc<T>
|
||||
impl<T> Repo for Rc<T>
|
||||
where
|
||||
T: Repo<'a, D>,
|
||||
T: Repo,
|
||||
{
|
||||
type Error = T::Error;
|
||||
type Future = T::Future;
|
||||
type Future<'a, Id: Dereference + 'a>
|
||||
where
|
||||
T: 'a,
|
||||
= T::Future<'a, Id>;
|
||||
|
||||
fn fetch(&'a self, id: &'a D) -> Self::Future {
|
||||
fn fetch<'a, Id: Dereference + 'a>(&'a self, id: Id) -> Self::Future<'a, Id> {
|
||||
T::fetch(self, id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, D: Dereference, T> Repo<'a, D> for Arc<T>
|
||||
impl<T> Repo for Arc<T>
|
||||
where
|
||||
T: Repo<'a, D>,
|
||||
T: Repo,
|
||||
{
|
||||
type Error = T::Error;
|
||||
type Future = T::Future;
|
||||
type Future<'a, Id: Dereference + 'a>
|
||||
where
|
||||
T: 'a,
|
||||
= T::Future<'a, Id>;
|
||||
|
||||
fn fetch(&'a self, id: &'a D) -> Self::Future {
|
||||
fn fetch<'a, Id: Dereference + 'a>(&'a self, id: Id) -> Self::Future<'a, Id> {
|
||||
T::fetch(self, id)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#![feature(generic_associated_types)]
|
||||
|
||||
pub mod deliver;
|
||||
pub mod deref;
|
||||
pub mod digest;
|
||||
pub mod ingest;
|
||||
pub mod object_id;
|
||||
pub mod resource;
|
||||
pub mod session;
|
||||
pub mod signature;
|
||||
|
|
89
apub-core/src/resource.rs
Normal file
89
apub-core/src/resource.rs
Normal file
|
@ -0,0 +1,89 @@
|
|||
use crate::deref::{Dereference, Repo};
|
||||
use std::{future::Future, marker::PhantomData};
|
||||
use url::Url;
|
||||
|
||||
pub trait ActivityPub<'a> {
|
||||
type Error;
|
||||
type Resource: Resource<ActivityPub = Self>;
|
||||
type Future: Future<
|
||||
Output = Result<<Self::Resource as Resource>::InternalRepresentation, Self::Error>,
|
||||
>;
|
||||
|
||||
fn to_internal(&'a self, resource: &'a Self::Resource) -> Self::Future;
|
||||
}
|
||||
|
||||
pub trait InternalRepresentation<'a> {
|
||||
type Error;
|
||||
type Resource: Resource<InternalRepresentation = Self>;
|
||||
type Future: Future<Output = Result<<Self::Resource as Resource>::ActivityPub, Self::Error>>;
|
||||
|
||||
fn to_activitypub(&'a self, resource: &'a Self::Resource) -> Self::Future;
|
||||
}
|
||||
|
||||
pub trait Delete<'a> {
|
||||
type Error;
|
||||
type Resource: Resource<ActivityPub = Self>;
|
||||
type Future: Future<Output = Result<<Self::Resource as Resource>::Tombstone, Self::Error>>;
|
||||
|
||||
fn delete(&'a self, resource: &'a Self::Resource) -> Self::Future;
|
||||
}
|
||||
|
||||
pub trait Resource {
|
||||
type Tombstone: serde::ser::Serialize + for<'de> serde::de::Deserialize<'de>;
|
||||
type ActivityPub: for<'a> ActivityPub<'a>
|
||||
+ for<'b> Delete<'b>
|
||||
+ serde::ser::Serialize
|
||||
+ for<'de> serde::de::Deserialize<'de>;
|
||||
type InternalRepresentation: for<'a> InternalRepresentation<'a>;
|
||||
}
|
||||
|
||||
pub async fn fetch<Res, Rep>(
|
||||
id: Url,
|
||||
repo: Rep,
|
||||
) -> Result<Option<Either<Res::ActivityPub, Res::Tombstone>>, Rep::Error>
|
||||
where
|
||||
Res: Resource,
|
||||
Rep: Repo,
|
||||
{
|
||||
let id: ObjectId<Res> = object_id(id);
|
||||
repo.fetch(id).await
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum Either<L, R> {
|
||||
Left(L),
|
||||
Right(R),
|
||||
}
|
||||
|
||||
struct ObjectId<R> {
|
||||
url: Url,
|
||||
_resource: PhantomData<fn() -> R>,
|
||||
}
|
||||
|
||||
impl<R> Clone for ObjectId<R> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
url: self.url.clone(),
|
||||
_resource: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn object_id<R: Resource>(url: Url) -> ObjectId<R> {
|
||||
ObjectId {
|
||||
url,
|
||||
_resource: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> Dereference for ObjectId<R>
|
||||
where
|
||||
R: Resource,
|
||||
{
|
||||
type Output = Either<R::ActivityPub, R::Tombstone>;
|
||||
|
||||
fn url(&self) -> &Url {
|
||||
&self.url
|
||||
}
|
||||
}
|
|
@ -23,23 +23,23 @@ pub struct RequestCountSession {
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct SessionError;
|
||||
|
||||
pub async fn guard<Fut, T, E, S>(fut: Fut, url: &Url, session: &S) -> Result<T, E>
|
||||
pub async fn guard<Fut, T, E, S>(fut: Fut, url: Url, session: &S) -> Result<T, E>
|
||||
where
|
||||
Fut: Future<Output = Result<T, E>>,
|
||||
E: From<SessionError>,
|
||||
S: Session,
|
||||
{
|
||||
if !session.should_procede(url) {
|
||||
if !session.should_procede(&url) {
|
||||
return Err(SessionError.into());
|
||||
}
|
||||
|
||||
match fut.await {
|
||||
Ok(t) => {
|
||||
session.mark_success(url);
|
||||
session.mark_success(&url);
|
||||
Ok(t)
|
||||
}
|
||||
Err(e) => {
|
||||
session.mark_failure(url);
|
||||
session.mark_failure(&url);
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(generic_associated_types)]
|
||||
|
||||
use apub_core::deref::{Dereference, Repo};
|
||||
use std::{
|
||||
future::Future,
|
||||
|
@ -20,8 +22,7 @@ pub enum Error<Left, Right> {
|
|||
Right(#[source] Right),
|
||||
}
|
||||
|
||||
type ClientError<'a, Id, Local, Http> =
|
||||
Error<<Local as Repo<'a, Id>>::Error, <Http as Repo<'a, Id>>::Error>;
|
||||
type ClientError<Local, Http> = Error<<Local as Repo>::Error, <Http as Repo>::Error>;
|
||||
|
||||
impl<Local, Http> Client<Local, Http> {
|
||||
pub fn new(local_domain: String, local: Local, http: Http) -> Self {
|
||||
|
@ -34,27 +35,29 @@ impl<Local, Http> Client<Local, Http> {
|
|||
|
||||
pub async fn dereference<'a, Id>(
|
||||
&'a self,
|
||||
id: &'a Id,
|
||||
) -> Result<Option<<Id as Dereference>::Output>, ClientError<'a, Id, Local, Http>>
|
||||
id: Id,
|
||||
) -> Result<Option<<Id as Dereference>::Output>, ClientError<Local, Http>>
|
||||
where
|
||||
Id: Dereference,
|
||||
Local: Repo<'a, Id> + 'a,
|
||||
Http: Repo<'a, Id> + 'a,
|
||||
Id: Dereference + Clone + 'a,
|
||||
Local: Repo + 'a,
|
||||
Http: Repo + 'a,
|
||||
{
|
||||
self.fetch(id).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Id, Local, Http> Repo<'a, Id> for Client<Local, Http>
|
||||
impl<Local, Http> Repo for Client<Local, Http>
|
||||
where
|
||||
Id: Dereference + 'a,
|
||||
Local: Repo<'a, Id> + 'a,
|
||||
Http: Repo<'a, Id> + 'a,
|
||||
Local: Repo,
|
||||
Http: Repo,
|
||||
{
|
||||
type Error = ClientError<'a, Id, Local, Http>;
|
||||
type Future = DereferenceFuture<'a, Id, Local, Http>;
|
||||
type Error = ClientError<Local, Http>;
|
||||
type Future<'a, Id: Dereference + 'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= DereferenceFuture<'a, Id, Local, Http>;
|
||||
|
||||
fn fetch(&'a self, id: &'a Id) -> Self::Future {
|
||||
fn fetch<'a, Id: Dereference + 'a>(&'a self, id: Id) -> Self::Future<'a, Id> {
|
||||
DereferenceFuture {
|
||||
id,
|
||||
client: self,
|
||||
|
@ -66,19 +69,23 @@ where
|
|||
pin_project_lite::pin_project! {
|
||||
#[project = DereferenceFutureInnerProj]
|
||||
#[project_replace = DereferenceFutureInnerProjReplace]
|
||||
enum DereferenceFutureInner<'a, Id: Dereference, Local, Http>
|
||||
enum DereferenceFutureInner<'a, Id, Local, Http>
|
||||
where
|
||||
Local: Repo<'a, Id>,
|
||||
Http: Repo<'a, Id>,
|
||||
Id: Dereference,
|
||||
Id: 'a,
|
||||
Local: Repo,
|
||||
Local: 'a,
|
||||
Http: Repo,
|
||||
Http: 'a,
|
||||
{
|
||||
Pending,
|
||||
Local {
|
||||
#[pin]
|
||||
future: <Local as Repo<'a, Id>>::Future,
|
||||
future: <Local as Repo>::Future<'a, Id>,
|
||||
},
|
||||
Http {
|
||||
#[pin]
|
||||
future: <Http as Repo<'a, Id>>::Future,
|
||||
future: <Http as Repo>::Future<'a, Id>,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,10 +93,10 @@ pin_project_lite::pin_project! {
|
|||
pin_project_lite::pin_project! {
|
||||
pub struct DereferenceFuture<'a, Id: Dereference, Local, Http>
|
||||
where
|
||||
Local: Repo<'a, Id>,
|
||||
Http: Repo<'a, Id>,
|
||||
Local: Repo,
|
||||
Http: Repo,
|
||||
{
|
||||
id: &'a Id,
|
||||
id: Id,
|
||||
client: &'a Client<Local, Http>,
|
||||
|
||||
#[pin]
|
||||
|
@ -100,10 +107,10 @@ pin_project_lite::pin_project! {
|
|||
impl<'a, Id, Local, Http> Future for DereferenceFuture<'a, Id, Local, Http>
|
||||
where
|
||||
Id: Dereference + 'a,
|
||||
Local: Repo<'a, Id>,
|
||||
Http: Repo<'a, Id>,
|
||||
Local: Repo,
|
||||
Http: Repo,
|
||||
{
|
||||
type Output = Result<Option<<Id as Dereference>::Output>, ClientError<'a, Id, Local, Http>>;
|
||||
type Output = Result<Option<<Id as Dereference>::Output>, ClientError<Local, Http>>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut this = self.as_mut().project();
|
||||
|
@ -111,7 +118,7 @@ where
|
|||
match this.state.as_mut().project() {
|
||||
DereferenceFutureInnerProj::Pending => {
|
||||
this.state.project_replace(DereferenceFutureInner::Local {
|
||||
future: this.client.local.fetch(this.id),
|
||||
future: this.client.local.fetch(this.id.clone()),
|
||||
});
|
||||
|
||||
self.poll(cx)
|
||||
|
@ -124,7 +131,7 @@ where
|
|||
}
|
||||
Poll::Ready(Ok(None)) => {
|
||||
this.state.project_replace(DereferenceFutureInner::Http {
|
||||
future: this.client.http.fetch(this.id),
|
||||
future: this.client.http.fetch(this.id.clone()),
|
||||
});
|
||||
|
||||
self.poll(cx)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(generic_associated_types)]
|
||||
|
||||
use apub_core::{
|
||||
deref::{Dereference, Repo},
|
||||
digest::{Digest, DigestBuilder, DigestFactory},
|
||||
|
@ -90,7 +92,7 @@ where
|
|||
|
||||
async fn do_fetch<Id>(
|
||||
&self,
|
||||
id: &Id,
|
||||
id: Id,
|
||||
) -> Result<Option<<Id as Dereference>::Output>, ReqwestError<SignTraitError<Crypto>>>
|
||||
where
|
||||
Id: Dereference,
|
||||
|
@ -112,27 +114,24 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, Id, CurrentSession, Crypto> Repo<'a, Id> for ReqwestClient<'a, CurrentSession, Crypto>
|
||||
impl<'b, CurrentSession, Crypto> Repo for ReqwestClient<'b, CurrentSession, Crypto>
|
||||
where
|
||||
Id: Dereference + Send + Sync,
|
||||
<Id as Dereference>::Output: 'static,
|
||||
CurrentSession: Session + Send + Sync,
|
||||
Crypto: SignFactory + Send + Sync,
|
||||
<Crypto as SignFactory>::KeyId: Send,
|
||||
{
|
||||
type Error = ReqwestError<SignTraitError<Crypto>>;
|
||||
type Future = Pin<
|
||||
Box<
|
||||
dyn Future<Output = Result<Option<<Id as Dereference>::Output>, Self::Error>>
|
||||
+ Send
|
||||
+ 'a,
|
||||
>,
|
||||
>;
|
||||
type Future<'a, Id: Dereference + 'a>
|
||||
where
|
||||
'b: 'a,
|
||||
Self: 'a,
|
||||
= Pin<Box<dyn Future<Output = Result<Option<Id::Output>, Self::Error>> + Send + 'a>>;
|
||||
|
||||
fn fetch(&'a self, id: &'a Id) -> Self::Future {
|
||||
fn fetch<'a, Id: Dereference + 'a>(&'a self, id: Id) -> Self::Future<'a, Id> {
|
||||
let url = id.url().clone();
|
||||
Box::pin(apub_core::session::guard(
|
||||
self.do_fetch(id),
|
||||
id.url(),
|
||||
url,
|
||||
&self.session,
|
||||
))
|
||||
}
|
||||
|
@ -184,7 +183,7 @@ where
|
|||
|
||||
Ok(())
|
||||
},
|
||||
inbox,
|
||||
inbox.clone(),
|
||||
&self.session,
|
||||
))
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#![feature(generic_associated_types)]
|
||||
|
||||
use actix_web::{middleware::Logger, web, App, HttpServer, ResponseError};
|
||||
use apub_actix_web::{
|
||||
inbox, serve_objects, RepoFactory, RepoFactoryX, SignatureConfig, Verifier, VerifyError,
|
||||
};
|
||||
use apub_actix_web::{inbox, serve_objects, RepoFactory, SignatureConfig, Verifier, VerifyError};
|
||||
use apub_core::{
|
||||
deref::{Dereference, Repo},
|
||||
digest::DigestFactory,
|
||||
|
@ -57,15 +57,14 @@ impl MemoryRepo {
|
|||
|
||||
impl ResponseError for ServerError {}
|
||||
|
||||
impl<'a, D> Repo<'a, D> for MemoryRepo
|
||||
where
|
||||
D: Dereference,
|
||||
D::Output: 'static,
|
||||
{
|
||||
impl Repo for MemoryRepo {
|
||||
type Error = serde_json::Error;
|
||||
type Future = Ready<Result<Option<D::Output>, Self::Error>>;
|
||||
type Future<'a, Id: Dereference + 'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= Ready<Result<Option<Id::Output>, Self::Error>>;
|
||||
|
||||
fn fetch(&'a self, id: &'a D) -> Self::Future {
|
||||
fn fetch<'a, D: Dereference + 'a>(&'a self, id: D) -> Self::Future<'a, D> {
|
||||
if let Some(obj_ref) = self.inner.get(id.url()) {
|
||||
match serde_json::from_value(obj_ref.clone()) {
|
||||
Ok(output) => ready(Ok(Some(output))),
|
||||
|
@ -77,15 +76,14 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, D> RepoFactory<'a, D> for MemoryRepo
|
||||
where
|
||||
D: Dereference,
|
||||
D::Output: 'static,
|
||||
{
|
||||
impl RepoFactory for MemoryRepo {
|
||||
type RepoError = serde_json::Error;
|
||||
type Repo = &'a MemoryRepo;
|
||||
type Repo<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= &'a MemoryRepo;
|
||||
|
||||
fn repo(&'a self) -> Self::Repo {
|
||||
fn repo<'a>(&'a self) -> Self::Repo<'a> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -95,32 +93,18 @@ impl Verifier for RequestVerifier {
|
|||
type Verify = RsaVerifier;
|
||||
}
|
||||
|
||||
impl<'a, D> RepoFactory<'a, D> for RequestVerifier
|
||||
where
|
||||
D: Dereference,
|
||||
D::Output: 'static,
|
||||
{
|
||||
impl RepoFactory for RequestVerifier {
|
||||
type RepoError = serde_json::Error;
|
||||
type Repo = &'a MemoryRepo;
|
||||
type Repo<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= &'a MemoryRepo;
|
||||
|
||||
fn repo(&'a self) -> Self::Repo {
|
||||
fn repo<'a>(&'a self) -> Self::Repo<'a> {
|
||||
&self.repo
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> RepoFactoryX<D> for RequestVerifier
|
||||
where
|
||||
D: Dereference,
|
||||
D::Output: 'static,
|
||||
{
|
||||
type RepoError = serde_json::Error;
|
||||
type RepoFactory = Self;
|
||||
|
||||
fn factory(&self) -> &Self::RepoFactory {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl DigestFactory for RequestVerifier {
|
||||
type Digest = Sha256Digest;
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ where
|
|||
repo: &'a R,
|
||||
) -> Result<Option<<Self as Dereference>::Output>, Box<dyn std::error::Error>>
|
||||
where
|
||||
R: Repo<'a, Self>,
|
||||
R: Repo,
|
||||
{
|
||||
Ok(repo.fetch(self).await?)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue