Merge branch 'main' into upgrade-deps6
This commit is contained in:
commit
6945b8dd3a
5 changed files with 135 additions and 3 deletions
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "activitypub_federation"
|
||||
version = "0.6.2"
|
||||
version = "0.6.5"
|
||||
edition = "2021"
|
||||
description = "High-level Activitypub framework"
|
||||
keywords = ["activitypub", "activitystreams", "federation", "fediverse"]
|
||||
|
|
@ -75,7 +75,8 @@ tokio = { version = "1.43.0", features = [
|
|||
"time",
|
||||
] }
|
||||
futures = "0.3.31"
|
||||
moka = { version = "0.12.10", features = ["future"] }
|
||||
moka = { version = "0.12.8", features = ["future"] }
|
||||
either = "1.15.0"
|
||||
|
||||
# Actix-web
|
||||
actix-web = { version = "4.9.0", default-features = false, optional = true }
|
||||
|
|
|
|||
|
|
@ -39,4 +39,4 @@ let user: DbUser = webfinger_resolve_actor("ruud@lemmy.world", &data).await?;
|
|||
# }).unwrap();
|
||||
```
|
||||
|
||||
Note that webfinger queries don't contain a leading `@`. It is possible tha there are multiple Activitypub IDs returned for a single webfinger query in case of multiple actors with the same name (for example Lemmy permits group and person with the same name). In this case `webfinger_resolve_actor` automatically loops and returns the first item which can be dereferenced successfully to the given type.
|
||||
Note that webfinger queries don't contain a leading `@`. It is possible that there are multiple Activitypub IDs returned for a single webfinger query in case of multiple actors with the same name (for example Lemmy permits group and person with the same name). In this case `webfinger_resolve_actor` automatically loops and returns the first item which can be dereferenced successfully to the given type.
|
||||
|
|
|
|||
|
|
@ -53,6 +53,10 @@ impl Keypair {
|
|||
}
|
||||
|
||||
/// Generate a random asymmetric keypair for ActivityPub HTTP signatures.
|
||||
///
|
||||
/// Note that this method is very slow in debug mode. To make it faster, follow
|
||||
/// instructions in the RSA crate's readme.
|
||||
/// <https://github.com/RustCrypto/RSA/blob/master/README.md>
|
||||
pub fn generate_actor_keypair() -> Result<Keypair, Error> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let rsa = RsaPrivateKey::new(&mut rng, 2048)?;
|
||||
|
|
|
|||
124
src/traits/either.rs
Normal file
124
src/traits/either.rs
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
use super::{Actor, Object};
|
||||
use crate::{config::Data, error::Error};
|
||||
use async_trait::async_trait;
|
||||
use chrono::{DateTime, Utc};
|
||||
use either::Either;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Debug;
|
||||
use url::Url;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum UntaggedEither<L, R> {
|
||||
Left(L),
|
||||
Right(R),
|
||||
}
|
||||
|
||||
impl<T, R, E, D> Object for Either<T, R>
|
||||
where
|
||||
T: Object + Object<Error = E, DataType = D> + Send,
|
||||
R: Object + Object<Error = E, DataType = D> + Send,
|
||||
<T as Object>::Kind: Send + Sync,
|
||||
<R as Object>::Kind: Send + Sync,
|
||||
D: Sync + Send + Clone,
|
||||
E: From<Error> + Debug,
|
||||
{
|
||||
type DataType = D;
|
||||
type Kind = UntaggedEither<T::Kind, R::Kind>;
|
||||
type Error = E;
|
||||
|
||||
fn last_refreshed_at(&self) -> Option<DateTime<Utc>> {
|
||||
match self {
|
||||
Either::Left(l) => l.last_refreshed_at(),
|
||||
Either::Right(r) => r.last_refreshed_at(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn read_from_id(
|
||||
object_id: Url,
|
||||
data: &Data<Self::DataType>,
|
||||
) -> Result<Option<Self>, Self::Error> {
|
||||
let l = T::read_from_id(object_id.clone(), data).await?;
|
||||
if let Some(l) = l {
|
||||
return Ok(Some(Either::Left(l)));
|
||||
}
|
||||
let r = R::read_from_id(object_id.clone(), data).await?;
|
||||
if let Some(r) = r {
|
||||
return Ok(Some(Either::Right(r)));
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
async fn delete(self, data: &Data<Self::DataType>) -> Result<(), Self::Error> {
|
||||
match self {
|
||||
Either::Left(l) => l.delete(data).await,
|
||||
Either::Right(r) => r.delete(data).await,
|
||||
}
|
||||
}
|
||||
|
||||
async fn into_json(self, data: &Data<Self::DataType>) -> Result<Self::Kind, Self::Error> {
|
||||
Ok(match self {
|
||||
Either::Left(l) => UntaggedEither::Left(l.into_json(data).await?),
|
||||
Either::Right(r) => UntaggedEither::Right(r.into_json(data).await?),
|
||||
})
|
||||
}
|
||||
|
||||
async fn verify(
|
||||
json: &Self::Kind,
|
||||
expected_domain: &Url,
|
||||
data: &Data<Self::DataType>,
|
||||
) -> Result<(), Self::Error> {
|
||||
match json {
|
||||
UntaggedEither::Left(l) => T::verify(l, expected_domain, data).await?,
|
||||
UntaggedEither::Right(r) => R::verify(r, expected_domain, data).await?,
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn from_json(json: Self::Kind, data: &Data<Self::DataType>) -> Result<Self, Self::Error> {
|
||||
Ok(match json {
|
||||
UntaggedEither::Left(l) => Either::Left(T::from_json(l, data).await?),
|
||||
UntaggedEither::Right(r) => Either::Right(R::from_json(r, data).await?),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<T, R, E, D> Actor for Either<T, R>
|
||||
where
|
||||
T: Actor + Object + Object<Error = E, DataType = D> + Send + 'static,
|
||||
R: Actor + Object + Object<Error = E, DataType = D> + Send + 'static,
|
||||
<T as Object>::Kind: Send + Sync,
|
||||
<R as Object>::Kind: Send + Sync,
|
||||
D: Sync + Send + Clone,
|
||||
E: From<Error> + Debug,
|
||||
{
|
||||
fn id(&self) -> Url {
|
||||
match self {
|
||||
Either::Left(l) => l.id(),
|
||||
Either::Right(r) => r.id(),
|
||||
}
|
||||
}
|
||||
|
||||
fn public_key_pem(&self) -> &str {
|
||||
match self {
|
||||
Either::Left(l) => l.public_key_pem(),
|
||||
Either::Right(r) => r.public_key_pem(),
|
||||
}
|
||||
}
|
||||
|
||||
fn private_key_pem(&self) -> Option<String> {
|
||||
match self {
|
||||
Either::Left(l) => l.private_key_pem(),
|
||||
Either::Right(r) => r.private_key_pem(),
|
||||
}
|
||||
}
|
||||
|
||||
fn inbox(&self) -> Url {
|
||||
match self {
|
||||
Either::Left(l) => l.inbox(),
|
||||
Either::Right(r) => r.inbox(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,9 @@ use serde::Deserialize;
|
|||
use std::{fmt::Debug, ops::Deref};
|
||||
use url::Url;
|
||||
|
||||
/// `Either` implementations for traits
|
||||
pub mod either;
|
||||
|
||||
/// Helper for converting between database structs and federated protocol structs.
|
||||
///
|
||||
/// ```
|
||||
Loading…
Reference in a new issue