forked from mirrors/relay
Fully lean on activitystreams-new
This commit is contained in:
parent
0b2763ab8b
commit
729e425e32
27 changed files with 514 additions and 544 deletions
483
Cargo.lock
generated
483
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -14,10 +14,11 @@ build = "src/build.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
actix-rt = "1.0.0"
|
actix-rt = "1.1.1"
|
||||||
actix-web = { version = "3.0.0-alpha.1", features = ["rustls"] }
|
actix-web = { version = "3.0.0-alpha.2", features = ["rustls"] }
|
||||||
actix-webfinger = "0.3.0-alpha.6"
|
actix-webfinger = "0.3.0-alpha.6"
|
||||||
activitystreams = "0.5.0"
|
activitystreams-new = { git = "https://git.asonix.dog/asonix/activitystreams-sketch" }
|
||||||
|
activitystreams-ext = { git = "https://git.asonix.dog/asonix/activitystreams-ext" }
|
||||||
ammonia = "3.1.0"
|
ammonia = "3.1.0"
|
||||||
async-trait = "0.1.24"
|
async-trait = "0.1.24"
|
||||||
background-jobs = "0.8.0-alpha.2"
|
background-jobs = "0.8.0-alpha.2"
|
||||||
|
|
183
src/apub.rs
183
src/apub.rs
|
@ -1,15 +1,14 @@
|
||||||
use activitystreams::{
|
use activitystreams_ext::{Ext1, UnparsedExtension};
|
||||||
actor::Actor,
|
use activitystreams_new::{
|
||||||
ext::Extension,
|
activity::ActorAndObject,
|
||||||
object::{Object, ObjectBox},
|
actor::{Actor, ApActor},
|
||||||
primitives::XsdAnyUri,
|
primitives::XsdAnyUri,
|
||||||
Base, BaseBox, PropRefs,
|
unparsed::UnparsedMutExt,
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct PublicKey {
|
pub struct PublicKeyInner {
|
||||||
pub id: XsdAnyUri,
|
pub id: XsdAnyUri,
|
||||||
pub owner: XsdAnyUri,
|
pub owner: XsdAnyUri,
|
||||||
pub public_key_pem: String,
|
pub public_key_pem: String,
|
||||||
|
@ -17,21 +16,8 @@ pub struct PublicKey {
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct PublicKeyExtension {
|
pub struct PublicKey {
|
||||||
pub public_key: PublicKey,
|
pub public_key: PublicKeyInner,
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize, PropRefs)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
#[prop_refs(Object)]
|
|
||||||
pub struct AnyExistingObject {
|
|
||||||
pub id: XsdAnyUri,
|
|
||||||
|
|
||||||
#[serde(rename = "type")]
|
|
||||||
pub kind: String,
|
|
||||||
|
|
||||||
#[serde(flatten)]
|
|
||||||
ext: HashMap<String, serde_json::Value>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize)]
|
||||||
|
@ -47,141 +33,32 @@ pub enum ValidTypes {
|
||||||
Update,
|
Update,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(untagged)]
|
#[serde(rename_all = "PascalCase")]
|
||||||
#[serde(rename_all = "camelCase")]
|
pub enum UndoTypes {
|
||||||
pub enum ValidObjects {
|
Follow,
|
||||||
Id(XsdAnyUri),
|
Announce,
|
||||||
Object(AnyExistingObject),
|
Create,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
pub type AcceptedUndoObjects = ActorAndObject<UndoTypes>;
|
||||||
#[serde(rename_all = "camelCase")]
|
pub type AcceptedActivities = ActorAndObject<ValidTypes>;
|
||||||
pub struct AcceptedObjects {
|
pub type AcceptedActors = Ext1<ApActor<Actor<String>>, PublicKey>;
|
||||||
pub id: XsdAnyUri,
|
|
||||||
|
|
||||||
#[serde(rename = "type")]
|
impl<U> UnparsedExtension<U> for PublicKey
|
||||||
pub kind: ValidTypes,
|
where
|
||||||
|
U: UnparsedMutExt,
|
||||||
|
{
|
||||||
|
type Error = serde_json::Error;
|
||||||
|
|
||||||
pub actor: XsdAnyUri,
|
fn try_from_unparsed(unparsed_mut: &mut U) -> Result<Self, Self::Error> {
|
||||||
|
Ok(PublicKey {
|
||||||
|
public_key: unparsed_mut.remove("publicKey")?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub object: ValidObjects,
|
fn try_into_unparsed(self, unparsed_mut: &mut U) -> Result<(), Self::Error> {
|
||||||
|
unparsed_mut.insert("publicKey", self.public_key)?;
|
||||||
#[serde(flatten)]
|
Ok(())
|
||||||
ext: HashMap<String, serde_json::Value>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct AcceptedActors {
|
|
||||||
pub id: XsdAnyUri,
|
|
||||||
|
|
||||||
#[serde(rename = "type")]
|
|
||||||
pub kind: String,
|
|
||||||
|
|
||||||
pub inbox: XsdAnyUri,
|
|
||||||
|
|
||||||
pub endpoints: Endpoints,
|
|
||||||
|
|
||||||
pub public_key: PublicKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct Endpoints {
|
|
||||||
shared_inbox: Option<XsdAnyUri>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PublicKey {
|
|
||||||
pub fn into_ext(self) -> PublicKeyExtension {
|
|
||||||
self.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<PublicKey> for PublicKeyExtension {
|
|
||||||
fn from(public_key: PublicKey) -> Self {
|
|
||||||
PublicKeyExtension { public_key }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Extension<T> for PublicKeyExtension where T: Actor {}
|
|
||||||
|
|
||||||
impl ValidObjects {
|
|
||||||
pub fn id(&self) -> &XsdAnyUri {
|
|
||||||
match self {
|
|
||||||
ValidObjects::Id(ref id) => id,
|
|
||||||
ValidObjects::Object(ref obj) => &obj.id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kind(&self) -> Option<&str> {
|
|
||||||
match self {
|
|
||||||
ValidObjects::Id(_) => None,
|
|
||||||
ValidObjects::Object(AnyExistingObject { kind, .. }) => Some(kind),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_kind(&self, query_kind: &str) -> bool {
|
|
||||||
match self {
|
|
||||||
ValidObjects::Id(_) => false,
|
|
||||||
ValidObjects::Object(AnyExistingObject { kind, .. }) => kind == query_kind,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is(&self, uri: &XsdAnyUri) -> bool {
|
|
||||||
match self {
|
|
||||||
ValidObjects::Id(id) => id == uri,
|
|
||||||
ValidObjects::Object(AnyExistingObject { id, .. }) => id == uri,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn child_object_id(&self) -> Option<XsdAnyUri> {
|
|
||||||
match self {
|
|
||||||
ValidObjects::Id(_) => None,
|
|
||||||
ValidObjects::Object(AnyExistingObject { ext, .. }) => {
|
|
||||||
if let Some(o) = ext.get("object") {
|
|
||||||
if let Ok(child_uri) = serde_json::from_value::<XsdAnyUri>(o.clone()) {
|
|
||||||
return Some(child_uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn child_object_is(&self, uri: &XsdAnyUri) -> bool {
|
|
||||||
if let Some(child_object_id) = self.child_object_id() {
|
|
||||||
return *uri == child_object_id;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn child_actor_id(&self) -> Option<XsdAnyUri> {
|
|
||||||
match self {
|
|
||||||
ValidObjects::Id(_) => None,
|
|
||||||
ValidObjects::Object(AnyExistingObject { ext, .. }) => {
|
|
||||||
if let Some(o) = ext.get("actor") {
|
|
||||||
if let Ok(child_uri) = serde_json::from_value::<XsdAnyUri>(o.clone()) {
|
|
||||||
return Some(child_uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn child_actor_is(&self, uri: &XsdAnyUri) -> bool {
|
|
||||||
if let Some(child_actor_id) = self.child_actor_id() {
|
|
||||||
return *uri == child_actor_id;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AcceptedActors {
|
|
||||||
pub fn inbox(&self) -> &XsdAnyUri {
|
|
||||||
self.endpoints.shared_inbox.as_ref().unwrap_or(&self.inbox)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{apub::AcceptedActors, db::Db, error::MyError, requests::Requests};
|
use crate::{apub::AcceptedActors, db::Db, error::MyError, requests::Requests};
|
||||||
use activitystreams::primitives::XsdAnyUri;
|
use activitystreams_new::{prelude::*, primitives::XsdAnyUri};
|
||||||
use log::error;
|
use log::error;
|
||||||
use std::{collections::HashSet, sync::Arc, time::Duration};
|
use std::{collections::HashSet, sync::Arc, time::Duration};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
@ -61,7 +61,8 @@ impl ActorCache {
|
||||||
let accepted_actor = requests.fetch::<AcceptedActors>(id.as_str()).await?;
|
let accepted_actor = requests.fetch::<AcceptedActors>(id.as_str()).await?;
|
||||||
|
|
||||||
let input_host = id.as_url().host();
|
let input_host = id.as_url().host();
|
||||||
let actor_host = accepted_actor.id.as_url().host();
|
let accepted_actor_id = accepted_actor.id().ok_or(MyError::MissingId)?;
|
||||||
|
let actor_host = accepted_actor_id.as_url().host();
|
||||||
let inbox_host = accepted_actor.inbox().as_url().host();
|
let inbox_host = accepted_actor.inbox().as_url().host();
|
||||||
|
|
||||||
if input_host != actor_host {
|
if input_host != actor_host {
|
||||||
|
@ -81,9 +82,9 @@ impl ActorCache {
|
||||||
let inbox = accepted_actor.inbox().clone();
|
let inbox = accepted_actor.inbox().clone();
|
||||||
|
|
||||||
let actor = Actor {
|
let actor = Actor {
|
||||||
id: accepted_actor.id,
|
id: accepted_actor_id.clone(),
|
||||||
public_key: accepted_actor.public_key.public_key_pem,
|
public_key: accepted_actor.ext_one.public_key.public_key_pem,
|
||||||
public_key_id: accepted_actor.public_key.id,
|
public_key_id: accepted_actor.ext_one.public_key.id,
|
||||||
inbox,
|
inbox,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{db::Db, error::MyError};
|
use crate::{db::Db, error::MyError};
|
||||||
use activitystreams::primitives::XsdAnyUri;
|
use activitystreams_new::primitives::XsdAnyUri;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::join;
|
use futures::join;
|
||||||
use lru::LruCache;
|
use lru::LruCache;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{db::Db, error::MyError};
|
use crate::{db::Db, error::MyError};
|
||||||
use activitystreams::primitives::XsdAnyUri;
|
use activitystreams_new::primitives::XsdAnyUri;
|
||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
error::MyError,
|
error::MyError,
|
||||||
requests::Requests,
|
requests::Requests,
|
||||||
};
|
};
|
||||||
use activitystreams::primitives::XsdAnyUri;
|
use activitystreams_new::primitives::XsdAnyUri;
|
||||||
use actix_rt::{
|
use actix_rt::{
|
||||||
spawn,
|
spawn,
|
||||||
time::{interval_at, Instant},
|
time::{interval_at, Instant},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::error::MyError;
|
use crate::error::MyError;
|
||||||
use activitystreams::primitives::XsdAnyUri;
|
use activitystreams_new::primitives::XsdAnyUri;
|
||||||
use deadpool_postgres::{Manager, Pool};
|
use deadpool_postgres::{Manager, Pool};
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use rsa::RSAPrivateKey;
|
use rsa::RSAPrivateKey;
|
||||||
|
|
18
src/error.rs
18
src/error.rs
|
@ -1,4 +1,4 @@
|
||||||
use activitystreams::primitives::XsdAnyUriError;
|
use activitystreams_new::primitives::XsdAnyUriError;
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
error::{BlockingError, ResponseError},
|
error::{BlockingError, ResponseError},
|
||||||
http::StatusCode,
|
http::StatusCode,
|
||||||
|
@ -96,6 +96,18 @@ pub enum MyError {
|
||||||
#[error("Response has invalid status code, {0}")]
|
#[error("Response has invalid status code, {0}")]
|
||||||
Status(StatusCode),
|
Status(StatusCode),
|
||||||
|
|
||||||
|
#[error("Expected an Object, found something else")]
|
||||||
|
ObjectFormat,
|
||||||
|
|
||||||
|
#[error("Expected a single object, found array")]
|
||||||
|
ObjectCount,
|
||||||
|
|
||||||
|
#[error("Input is missing a 'type' field")]
|
||||||
|
MissingKind,
|
||||||
|
|
||||||
|
#[error("Input is missing a 'id' field")]
|
||||||
|
MissingId,
|
||||||
|
|
||||||
#[error("URI is missing domain field")]
|
#[error("URI is missing domain field")]
|
||||||
Domain,
|
Domain,
|
||||||
|
|
||||||
|
@ -112,7 +124,9 @@ impl ResponseError for MyError {
|
||||||
| MyError::BadActor(_, _) => StatusCode::FORBIDDEN,
|
| MyError::BadActor(_, _) => StatusCode::FORBIDDEN,
|
||||||
MyError::NotSubscribed(_) => StatusCode::UNAUTHORIZED,
|
MyError::NotSubscribed(_) => StatusCode::UNAUTHORIZED,
|
||||||
MyError::Duplicate => StatusCode::ACCEPTED,
|
MyError::Duplicate => StatusCode::ACCEPTED,
|
||||||
MyError::Kind(_) => StatusCode::BAD_REQUEST,
|
MyError::Kind(_) | MyError::MissingKind | MyError::MissingId | MyError::ObjectCount => {
|
||||||
|
StatusCode::BAD_REQUEST
|
||||||
|
}
|
||||||
_ => StatusCode::INTERNAL_SERVER_ERROR,
|
_ => StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
DeliverMany, JobState,
|
DeliverMany, JobState,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use activitystreams::primitives::XsdAnyUri;
|
use activitystreams_new::{activity::Announce as AsAnnounce, primitives::XsdAnyUri};
|
||||||
use background_jobs::ActixJob;
|
use background_jobs::ActixJob;
|
||||||
use std::{future::Future, pin::Pin};
|
use std::{future::Future, pin::Pin};
|
||||||
|
|
||||||
|
@ -41,13 +41,11 @@ fn generate_announce(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
activity_id: &XsdAnyUri,
|
activity_id: &XsdAnyUri,
|
||||||
object_id: &XsdAnyUri,
|
object_id: &XsdAnyUri,
|
||||||
) -> Result<activitystreams::activity::Announce, MyError> {
|
) -> Result<AsAnnounce, MyError> {
|
||||||
let mut announce = activitystreams::activity::Announce::default();
|
let announce = AsAnnounce::new(
|
||||||
|
config.generate_url(UrlKind::Actor).parse::<XsdAnyUri>()?,
|
||||||
announce
|
object_id.clone(),
|
||||||
.announce_props
|
);
|
||||||
.set_object_xsd_any_uri(object_id.clone())?
|
|
||||||
.set_actor_xsd_any_uri(config.generate_url(UrlKind::Actor))?;
|
|
||||||
|
|
||||||
prepare_activity(
|
prepare_activity(
|
||||||
announce,
|
announce,
|
||||||
|
|
|
@ -1,23 +1,27 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
apub::AcceptedObjects,
|
apub::AcceptedActivities,
|
||||||
config::{Config, UrlKind},
|
config::{Config, UrlKind},
|
||||||
data::Actor,
|
data::Actor,
|
||||||
error::MyError,
|
error::MyError,
|
||||||
jobs::{apub::prepare_activity, Deliver, JobState},
|
jobs::{apub::prepare_activity, Deliver, JobState},
|
||||||
};
|
};
|
||||||
use activitystreams::primitives::XsdAnyUri;
|
use activitystreams_new::{
|
||||||
|
activity::{Accept as AsAccept, Follow as AsFollow},
|
||||||
|
prelude::*,
|
||||||
|
primitives::XsdAnyUri,
|
||||||
|
};
|
||||||
use background_jobs::ActixJob;
|
use background_jobs::ActixJob;
|
||||||
use std::{future::Future, pin::Pin};
|
use std::{future::Future, pin::Pin};
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
pub struct Follow {
|
pub struct Follow {
|
||||||
is_listener: bool,
|
is_listener: bool,
|
||||||
input: AcceptedObjects,
|
input: AcceptedActivities,
|
||||||
actor: Actor,
|
actor: Actor,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Follow {
|
impl Follow {
|
||||||
pub fn new(is_listener: bool, input: AcceptedObjects, actor: Actor) -> Self {
|
pub fn new(is_listener: bool, input: AcceptedActivities, actor: Actor) -> Self {
|
||||||
Follow {
|
Follow {
|
||||||
is_listener,
|
is_listener,
|
||||||
input,
|
input,
|
||||||
|
@ -32,7 +36,7 @@ impl Follow {
|
||||||
let my_id: XsdAnyUri = state.config.generate_url(UrlKind::Actor).parse()?;
|
let my_id: XsdAnyUri = state.config.generate_url(UrlKind::Actor).parse()?;
|
||||||
|
|
||||||
// if following relay directly, not just following 'public', followback
|
// if following relay directly, not just following 'public', followback
|
||||||
if self.input.object.is(&my_id) && !state.actors.is_following(&self.actor.id).await {
|
if self.input.object_is(&my_id) && !state.actors.is_following(&self.actor.id).await {
|
||||||
let follow = generate_follow(&state.config, &self.actor.id, &my_id)?;
|
let follow = generate_follow(&state.config, &self.actor.id, &my_id)?;
|
||||||
state
|
state
|
||||||
.job_server
|
.job_server
|
||||||
|
@ -41,7 +45,12 @@ impl Follow {
|
||||||
|
|
||||||
state.actors.follower(&self.actor).await?;
|
state.actors.follower(&self.actor).await?;
|
||||||
|
|
||||||
let accept = generate_accept_follow(&state.config, &self.actor.id, &self.input.id, &my_id)?;
|
let accept = generate_accept_follow(
|
||||||
|
&state.config,
|
||||||
|
&self.actor.id,
|
||||||
|
self.input.id().ok_or(MyError::MissingId)?,
|
||||||
|
&my_id,
|
||||||
|
)?;
|
||||||
|
|
||||||
state
|
state
|
||||||
.job_server
|
.job_server
|
||||||
|
@ -55,13 +64,8 @@ fn generate_follow(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
actor_id: &XsdAnyUri,
|
actor_id: &XsdAnyUri,
|
||||||
my_id: &XsdAnyUri,
|
my_id: &XsdAnyUri,
|
||||||
) -> Result<activitystreams::activity::Follow, MyError> {
|
) -> Result<AsFollow, MyError> {
|
||||||
let mut follow = activitystreams::activity::Follow::default();
|
let follow = AsFollow::new(my_id.clone(), actor_id.clone());
|
||||||
|
|
||||||
follow
|
|
||||||
.follow_props
|
|
||||||
.set_object_xsd_any_uri(actor_id.clone())?
|
|
||||||
.set_actor_xsd_any_uri(my_id.clone())?;
|
|
||||||
|
|
||||||
prepare_activity(
|
prepare_activity(
|
||||||
follow,
|
follow,
|
||||||
|
@ -76,23 +80,12 @@ fn generate_accept_follow(
|
||||||
actor_id: &XsdAnyUri,
|
actor_id: &XsdAnyUri,
|
||||||
input_id: &XsdAnyUri,
|
input_id: &XsdAnyUri,
|
||||||
my_id: &XsdAnyUri,
|
my_id: &XsdAnyUri,
|
||||||
) -> Result<activitystreams::activity::Accept, MyError> {
|
) -> Result<AsAccept, MyError> {
|
||||||
let mut accept = activitystreams::activity::Accept::default();
|
let mut follow = AsFollow::new(actor_id.clone(), my_id.clone());
|
||||||
|
|
||||||
accept
|
follow.set_id(input_id.clone());
|
||||||
.accept_props
|
|
||||||
.set_actor_xsd_any_uri(my_id.clone())?
|
|
||||||
.set_object_base_box({
|
|
||||||
let mut follow = activitystreams::activity::Follow::default();
|
|
||||||
|
|
||||||
follow.object_props.set_id(input_id.clone())?;
|
let accept = AsAccept::new(my_id.clone(), follow.into_any_base()?);
|
||||||
follow
|
|
||||||
.follow_props
|
|
||||||
.set_object_xsd_any_uri(my_id.clone())?
|
|
||||||
.set_actor_xsd_any_uri(actor_id.clone())?;
|
|
||||||
|
|
||||||
follow
|
|
||||||
})?;
|
|
||||||
|
|
||||||
prepare_activity(
|
prepare_activity(
|
||||||
accept,
|
accept,
|
||||||
|
|
|
@ -1,24 +1,30 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
apub::AcceptedObjects,
|
apub::AcceptedActivities,
|
||||||
data::Actor,
|
data::Actor,
|
||||||
|
error::MyError,
|
||||||
jobs::{apub::get_inboxes, DeliverMany, JobState},
|
jobs::{apub::get_inboxes, DeliverMany, JobState},
|
||||||
};
|
};
|
||||||
|
use activitystreams_new::prelude::*;
|
||||||
use background_jobs::ActixJob;
|
use background_jobs::ActixJob;
|
||||||
use std::{future::Future, pin::Pin};
|
use std::{future::Future, pin::Pin};
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
pub struct Forward {
|
pub struct Forward {
|
||||||
input: AcceptedObjects,
|
input: AcceptedActivities,
|
||||||
actor: Actor,
|
actor: Actor,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Forward {
|
impl Forward {
|
||||||
pub fn new(input: AcceptedObjects, actor: Actor) -> Self {
|
pub fn new(input: AcceptedActivities, actor: Actor) -> Self {
|
||||||
Forward { input, actor }
|
Forward { input, actor }
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn perform(self, state: JobState) -> Result<(), anyhow::Error> {
|
async fn perform(self, state: JobState) -> Result<(), anyhow::Error> {
|
||||||
let object_id = self.input.object.id();
|
let object_id = self
|
||||||
|
.input
|
||||||
|
.object()
|
||||||
|
.as_single_id()
|
||||||
|
.ok_or(MyError::MissingId)?;
|
||||||
|
|
||||||
let inboxes = get_inboxes(&state.state, &self.actor, object_id).await?;
|
let inboxes = get_inboxes(&state.state, &self.actor, object_id).await?;
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,12 @@ use crate::{
|
||||||
data::{Actor, State},
|
data::{Actor, State},
|
||||||
error::MyError,
|
error::MyError,
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams_new::{
|
||||||
context, object::properties::ObjectProperties, primitives::XsdAnyUri, security,
|
activity::{Follow as AsFollow, Undo as AsUndo},
|
||||||
|
context,
|
||||||
|
prelude::*,
|
||||||
|
primitives::XsdAnyUri,
|
||||||
|
security,
|
||||||
};
|
};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
|
@ -30,19 +34,18 @@ async fn get_inboxes(
|
||||||
Ok(state.listeners_without(&actor.inbox, &domain).await)
|
Ok(state.listeners_without(&actor.inbox, &domain).await)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_activity<T, U, V>(
|
fn prepare_activity<T, U, V, Kind>(
|
||||||
mut t: T,
|
mut t: T,
|
||||||
id: impl TryInto<XsdAnyUri, Error = U>,
|
id: impl TryInto<XsdAnyUri, Error = U>,
|
||||||
to: impl TryInto<XsdAnyUri, Error = V>,
|
to: impl TryInto<XsdAnyUri, Error = V>,
|
||||||
) -> Result<T, MyError>
|
) -> Result<T, MyError>
|
||||||
where
|
where
|
||||||
T: AsMut<ObjectProperties>,
|
T: ObjectExt<Kind> + BaseExt<Kind>,
|
||||||
MyError: From<U> + From<V>,
|
MyError: From<U> + From<V>,
|
||||||
{
|
{
|
||||||
t.as_mut()
|
t.set_id(id.try_into()?)
|
||||||
.set_id(id.try_into()?)?
|
.set_many_tos(vec![to.try_into()?])
|
||||||
.set_many_to_xsd_any_uris(vec![to.try_into()?])?
|
.set_many_contexts(vec![context(), security()]);
|
||||||
.set_many_context_xsd_any_uris(vec![context(), security()])?;
|
|
||||||
Ok(t)
|
Ok(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,24 +54,12 @@ fn generate_undo_follow(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
actor_id: &XsdAnyUri,
|
actor_id: &XsdAnyUri,
|
||||||
my_id: &XsdAnyUri,
|
my_id: &XsdAnyUri,
|
||||||
) -> Result<activitystreams::activity::Undo, MyError> {
|
) -> Result<AsUndo, MyError> {
|
||||||
let mut undo = activitystreams::activity::Undo::default();
|
let mut follow = AsFollow::new(my_id.clone(), actor_id.clone());
|
||||||
|
|
||||||
undo.undo_props
|
follow.set_id(config.generate_url(UrlKind::Activity).parse()?);
|
||||||
.set_actor_xsd_any_uri(my_id.clone())?
|
|
||||||
.set_object_base_box({
|
|
||||||
let mut follow = activitystreams::activity::Follow::default();
|
|
||||||
|
|
||||||
follow
|
let undo = AsUndo::new(my_id.clone(), follow.into_any_base()?);
|
||||||
.object_props
|
|
||||||
.set_id(config.generate_url(UrlKind::Activity))?;
|
|
||||||
follow
|
|
||||||
.follow_props
|
|
||||||
.set_actor_xsd_any_uri(actor_id.clone())?
|
|
||||||
.set_object_xsd_any_uri(actor_id.clone())?;
|
|
||||||
|
|
||||||
follow
|
|
||||||
})?;
|
|
||||||
|
|
||||||
prepare_activity(undo, config.generate_url(UrlKind::Actor), actor_id.clone())
|
prepare_activity(undo, config.generate_url(UrlKind::Actor), actor_id.clone())
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
||||||
data::Actor,
|
data::Actor,
|
||||||
jobs::{apub::generate_undo_follow, Deliver, JobState},
|
jobs::{apub::generate_undo_follow, Deliver, JobState},
|
||||||
};
|
};
|
||||||
use activitystreams::primitives::XsdAnyUri;
|
use activitystreams_new::primitives::XsdAnyUri;
|
||||||
use background_jobs::ActixJob;
|
use background_jobs::ActixJob;
|
||||||
use std::{future::Future, pin::Pin};
|
use std::{future::Future, pin::Pin};
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
apub::AcceptedObjects,
|
apub::AcceptedActivities,
|
||||||
config::UrlKind,
|
config::UrlKind,
|
||||||
data::Actor,
|
data::Actor,
|
||||||
jobs::{apub::generate_undo_follow, Deliver, JobState},
|
jobs::{apub::generate_undo_follow, Deliver, JobState},
|
||||||
};
|
};
|
||||||
use activitystreams::primitives::XsdAnyUri;
|
use activitystreams_new::primitives::XsdAnyUri;
|
||||||
use background_jobs::ActixJob;
|
use background_jobs::ActixJob;
|
||||||
use std::{future::Future, pin::Pin};
|
use std::{future::Future, pin::Pin};
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
pub struct Undo {
|
pub struct Undo {
|
||||||
input: AcceptedObjects,
|
input: AcceptedActivities,
|
||||||
actor: Actor,
|
actor: Actor,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Undo {
|
impl Undo {
|
||||||
pub fn new(input: AcceptedObjects, actor: Actor) -> Self {
|
pub fn new(input: AcceptedActivities, actor: Actor) -> Self {
|
||||||
Undo { input, actor }
|
Undo { input, actor }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{error::MyError, jobs::JobState};
|
use crate::{error::MyError, jobs::JobState};
|
||||||
use activitystreams::primitives::XsdAnyUri;
|
use activitystreams_new::primitives::XsdAnyUri;
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use background_jobs::{ActixJob, Backoff};
|
use background_jobs::{ActixJob, Backoff};
|
||||||
use std::{future::Future, pin::Pin};
|
use std::{future::Future, pin::Pin};
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
||||||
error::MyError,
|
error::MyError,
|
||||||
jobs::{Deliver, JobState},
|
jobs::{Deliver, JobState},
|
||||||
};
|
};
|
||||||
use activitystreams::primitives::XsdAnyUri;
|
use activitystreams_new::primitives::XsdAnyUri;
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use background_jobs::ActixJob;
|
use background_jobs::ActixJob;
|
||||||
use futures::future::{ready, Ready};
|
use futures::future::{ready, Ready};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{config::UrlKind, jobs::JobState};
|
use crate::{config::UrlKind, jobs::JobState};
|
||||||
use activitystreams::primitives::XsdAnyUri;
|
use activitystreams_new::primitives::XsdAnyUri;
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use background_jobs::ActixJob;
|
use background_jobs::ActixJob;
|
||||||
use futures::join;
|
use futures::join;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::jobs::JobState;
|
use crate::jobs::JobState;
|
||||||
use activitystreams::primitives::XsdAnyUri;
|
use activitystreams_new::primitives::XsdAnyUri;
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use background_jobs::ActixJob;
|
use background_jobs::ActixJob;
|
||||||
use std::{future::Future, pin::Pin};
|
use std::{future::Future, pin::Pin};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{data::ActorCache, error::MyError, requests::Requests};
|
use crate::{data::ActorCache, error::MyError, requests::Requests};
|
||||||
use activitystreams::primitives::XsdAnyUri;
|
use activitystreams_new::primitives::XsdAnyUri;
|
||||||
use actix_web::web;
|
use actix_web::web;
|
||||||
use http_signature_normalization_actix::{prelude::*, verify::DeprecatedAlgorithm};
|
use http_signature_normalization_actix::{prelude::*, verify::DeprecatedAlgorithm};
|
||||||
use log::error;
|
use log::error;
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
||||||
db::listen,
|
db::listen,
|
||||||
jobs::{JobServer, QueryInstance, QueryNodeinfo},
|
jobs::{JobServer, QueryInstance, QueryNodeinfo},
|
||||||
};
|
};
|
||||||
use activitystreams::primitives::XsdAnyUri;
|
use activitystreams_new::primitives::XsdAnyUri;
|
||||||
use actix_rt::{spawn, time::delay_for};
|
use actix_rt::{spawn, time::delay_for};
|
||||||
use futures::stream::{poll_fn, StreamExt};
|
use futures::stream::{poll_fn, StreamExt};
|
||||||
use log::{debug, error, warn};
|
use log::{debug, error, warn};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::error::MyError;
|
use crate::error::MyError;
|
||||||
use activitystreams::primitives::XsdAnyUri;
|
use activitystreams_new::primitives::XsdAnyUri;
|
||||||
use actix_web::{client::Client, http::header::Date};
|
use actix_web::{client::Client, http::header::Date};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use http_signature_normalization_actix::prelude::*;
|
use http_signature_normalization_actix::prelude::*;
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
apub::PublicKey,
|
apub::{PublicKey, PublicKeyInner},
|
||||||
config::{Config, UrlKind},
|
config::{Config, UrlKind},
|
||||||
data::State,
|
data::State,
|
||||||
error::MyError,
|
error::MyError,
|
||||||
routes::ok,
|
routes::ok,
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams_ext::Ext1;
|
||||||
actor::Application, context, endpoint::EndpointProperties, ext::Extensible,
|
use activitystreams_new::{
|
||||||
object::properties::ObjectProperties, security,
|
actor::{ApActor, Application, Endpoints},
|
||||||
|
context,
|
||||||
|
prelude::*,
|
||||||
|
primitives::{XsdAnyUri, XsdString},
|
||||||
|
security,
|
||||||
};
|
};
|
||||||
use actix_web::{web, Responder};
|
use actix_web::{web, Responder};
|
||||||
use rsa_pem::KeyExt;
|
use rsa_pem::KeyExt;
|
||||||
|
@ -16,33 +20,42 @@ pub async fn route(
|
||||||
state: web::Data<State>,
|
state: web::Data<State>,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
) -> Result<impl Responder, MyError> {
|
) -> Result<impl Responder, MyError> {
|
||||||
let mut application = Application::full();
|
let mut application = Ext1::new(
|
||||||
let mut endpoint = EndpointProperties::default();
|
ApActor::new(
|
||||||
|
config.generate_url(UrlKind::Inbox).parse()?,
|
||||||
endpoint.set_shared_inbox(config.generate_url(UrlKind::Inbox))?;
|
config.generate_url(UrlKind::Outbox).parse()?,
|
||||||
|
Application::new(),
|
||||||
let props: &mut ObjectProperties = application.as_mut();
|
),
|
||||||
props
|
PublicKey {
|
||||||
.set_id(config.generate_url(UrlKind::Actor))?
|
public_key: PublicKeyInner {
|
||||||
.set_summary_xsd_string("AodeRelay bot")?
|
id: config.generate_url(UrlKind::MainKey).parse()?,
|
||||||
.set_name_xsd_string("AodeRelay")?
|
owner: config.generate_url(UrlKind::Actor).parse()?,
|
||||||
.set_url_xsd_any_uri(config.generate_url(UrlKind::Actor))?
|
public_key_pem: state.public_key.to_pem_pkcs8()?,
|
||||||
.set_many_context_xsd_any_uris(vec![context(), security()])?;
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
application
|
application
|
||||||
.extension
|
.set_id(config.generate_url(UrlKind::Actor).parse()?)
|
||||||
.set_preferred_username("relay")?
|
.set_summary(XsdString::from("AodeRelay bot"))
|
||||||
.set_followers(config.generate_url(UrlKind::Followers))?
|
.set_name(XsdString::from("AodeRelay"))
|
||||||
.set_following(config.generate_url(UrlKind::Following))?
|
.set_url(config.generate_url(UrlKind::Actor).parse::<XsdAnyUri>()?)
|
||||||
.set_inbox(config.generate_url(UrlKind::Inbox))?
|
.set_many_contexts(vec![context(), security()])
|
||||||
.set_outbox(config.generate_url(UrlKind::Outbox))?
|
.set_preferred_username("relay".into())
|
||||||
.set_endpoints(endpoint)?;
|
.set_followers(
|
||||||
|
config
|
||||||
|
.generate_url(UrlKind::Followers)
|
||||||
|
.parse::<XsdAnyUri>()?,
|
||||||
|
)
|
||||||
|
.set_following(
|
||||||
|
config
|
||||||
|
.generate_url(UrlKind::Following)
|
||||||
|
.parse::<XsdAnyUri>()?,
|
||||||
|
)
|
||||||
|
.set_endpoints(Endpoints {
|
||||||
|
shared_inbox: Some(config.generate_url(UrlKind::Inbox).parse::<XsdAnyUri>()?),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
let public_key = PublicKey {
|
Ok(ok(application))
|
||||||
id: config.generate_url(UrlKind::MainKey).parse()?,
|
|
||||||
owner: config.generate_url(UrlKind::Actor).parse()?,
|
|
||||||
public_key_pem: state.public_key.to_pem_pkcs8()?,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(ok(application.extend(public_key.into_ext())))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
apub::{AcceptedObjects, ValidTypes},
|
apub::{AcceptedActivities, AcceptedUndoObjects, UndoTypes, ValidTypes},
|
||||||
config::{Config, UrlKind},
|
config::{Config, UrlKind},
|
||||||
data::{Actor, ActorCache, State},
|
data::{Actor, ActorCache, State},
|
||||||
error::MyError,
|
error::MyError,
|
||||||
|
@ -8,7 +8,13 @@ use crate::{
|
||||||
requests::Requests,
|
requests::Requests,
|
||||||
routes::accepted,
|
routes::accepted,
|
||||||
};
|
};
|
||||||
use activitystreams::{primitives::XsdAnyUri, public};
|
use activitystreams_new::{
|
||||||
|
activity,
|
||||||
|
base::AnyBase,
|
||||||
|
prelude::*,
|
||||||
|
primitives::{OneOrMany, XsdAnyUri},
|
||||||
|
public,
|
||||||
|
};
|
||||||
use actix_web::{web, HttpResponse};
|
use actix_web::{web, HttpResponse};
|
||||||
use futures::join;
|
use futures::join;
|
||||||
use http_signature_normalization_actix::prelude::{DigestVerified, SignatureVerified};
|
use http_signature_normalization_actix::prelude::{DigestVerified, SignatureVerified};
|
||||||
|
@ -20,12 +26,18 @@ pub async fn route(
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
client: web::Data<Requests>,
|
client: web::Data<Requests>,
|
||||||
jobs: web::Data<JobServer>,
|
jobs: web::Data<JobServer>,
|
||||||
input: web::Json<AcceptedObjects>,
|
input: web::Json<AcceptedActivities>,
|
||||||
verified: Option<(SignatureVerified, DigestVerified)>,
|
verified: Option<(SignatureVerified, DigestVerified)>,
|
||||||
) -> Result<HttpResponse, MyError> {
|
) -> Result<HttpResponse, MyError> {
|
||||||
let input = input.into_inner();
|
let input = input.into_inner();
|
||||||
|
|
||||||
let actor = actors.get(&input.actor, &client).await?.into_inner();
|
let actor = actors
|
||||||
|
.get(
|
||||||
|
input.actor().as_single_id().ok_or(MyError::MissingId)?,
|
||||||
|
&client,
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
.into_inner();
|
||||||
|
|
||||||
let (is_blocked, is_whitelisted, is_listener) = join!(
|
let (is_blocked, is_whitelisted, is_listener) = join!(
|
||||||
state.is_blocked(&actor.id),
|
state.is_blocked(&actor.id),
|
||||||
|
@ -41,7 +53,7 @@ pub async fn route(
|
||||||
return Err(MyError::Whitelist(actor.id.to_string()));
|
return Err(MyError::Whitelist(actor.id.to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !is_listener && !valid_without_listener(&input) {
|
if !is_listener && !valid_without_listener(&input)? {
|
||||||
return Err(MyError::NotSubscribed(actor.inbox.to_string()));
|
return Err(MyError::NotSubscribed(actor.inbox.to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +71,7 @@ pub async fn route(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match input.kind {
|
match input.kind().ok_or(MyError::MissingKind)? {
|
||||||
ValidTypes::Accept => handle_accept(&config, input).await?,
|
ValidTypes::Accept => handle_accept(&config, input).await?,
|
||||||
ValidTypes::Reject => handle_reject(&config, &jobs, input, actor).await?,
|
ValidTypes::Reject => handle_reject(&config, &jobs, input, actor).await?,
|
||||||
ValidTypes::Announce | ValidTypes::Create => {
|
ValidTypes::Announce | ValidTypes::Create => {
|
||||||
|
@ -73,26 +85,39 @@ pub async fn route(
|
||||||
Ok(accepted(serde_json::json!({})))
|
Ok(accepted(serde_json::json!({})))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn valid_without_listener(input: &AcceptedObjects) -> bool {
|
fn valid_without_listener(input: &AcceptedActivities) -> Result<bool, MyError> {
|
||||||
match input.kind {
|
match input.kind() {
|
||||||
ValidTypes::Follow => true,
|
Some(ValidTypes::Follow) => Ok(true),
|
||||||
ValidTypes::Undo if input.object.is_kind("Follow") => true,
|
Some(ValidTypes::Undo) => Ok(single_object(input.object())?.is_kind("Follow")),
|
||||||
_ => false,
|
_ => Ok(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_accept(config: &Config, input: AcceptedObjects) -> Result<(), MyError> {
|
fn kind_str(base: &AnyBase) -> Result<&str, MyError> {
|
||||||
if !input.object.is_kind("Follow") {
|
base.kind_str().ok_or(MyError::MissingKind)
|
||||||
return Err(MyError::Kind(
|
}
|
||||||
input.object.kind().unwrap_or("unknown").to_owned(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
if !input
|
fn id_string(id: Option<&XsdAnyUri>) -> Result<String, MyError> {
|
||||||
.object
|
id.map(|s| s.to_string()).ok_or(MyError::MissingId)
|
||||||
.child_actor_is(&config.generate_url(UrlKind::Actor).parse()?)
|
}
|
||||||
|
|
||||||
|
fn single_object(o: &OneOrMany<AnyBase>) -> Result<&AnyBase, MyError> {
|
||||||
|
o.as_one().ok_or(MyError::ObjectCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_accept(config: &Config, input: AcceptedActivities) -> Result<(), MyError> {
|
||||||
|
let follow = if let Ok(Some(follow)) =
|
||||||
|
activity::Follow::from_any_base(single_object(input.object())?.clone())
|
||||||
{
|
{
|
||||||
return Err(MyError::WrongActor(input.object.id().to_string()));
|
follow
|
||||||
|
} else {
|
||||||
|
return Err(MyError::Kind(
|
||||||
|
kind_str(single_object(input.object())?)?.to_owned(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
if !follow.actor_is(&config.generate_url(UrlKind::Actor).parse()?) {
|
||||||
|
return Err(MyError::WrongActor(id_string(follow.id())?));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -101,20 +126,23 @@ async fn handle_accept(config: &Config, input: AcceptedObjects) -> Result<(), My
|
||||||
async fn handle_reject(
|
async fn handle_reject(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
jobs: &JobServer,
|
jobs: &JobServer,
|
||||||
input: AcceptedObjects,
|
input: AcceptedActivities,
|
||||||
actor: Actor,
|
actor: Actor,
|
||||||
) -> Result<(), MyError> {
|
) -> Result<(), MyError> {
|
||||||
if !input.object.is_kind("Follow") {
|
let follow = if let Ok(Some(follow)) =
|
||||||
return Err(MyError::Kind(
|
activity::Follow::from_any_base(single_object(input.object())?.clone())
|
||||||
input.object.kind().unwrap_or("unknown").to_owned(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
if !input
|
|
||||||
.object
|
|
||||||
.child_actor_is(&config.generate_url(UrlKind::Actor).parse()?)
|
|
||||||
{
|
{
|
||||||
return Err(MyError::WrongActor(input.object.id().to_string()));
|
follow
|
||||||
|
} else {
|
||||||
|
return Err(MyError::Kind(
|
||||||
|
kind_str(single_object(input.object())?)?.to_owned(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
if !follow.actor_is(&config.generate_url(UrlKind::Actor).parse()?) {
|
||||||
|
return Err(MyError::WrongActor(
|
||||||
|
follow.id().map(|s| s.to_string()).unwrap_or(String::new()),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
jobs.queue(Reject(actor))?;
|
jobs.queue(Reject(actor))?;
|
||||||
|
@ -125,34 +153,27 @@ async fn handle_reject(
|
||||||
async fn handle_undo(
|
async fn handle_undo(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
jobs: &JobServer,
|
jobs: &JobServer,
|
||||||
input: AcceptedObjects,
|
input: AcceptedActivities,
|
||||||
actor: Actor,
|
actor: Actor,
|
||||||
is_listener: bool,
|
is_listener: bool,
|
||||||
) -> Result<(), MyError> {
|
) -> Result<(), MyError> {
|
||||||
match input.object.kind() {
|
let any_base = single_object(input.object())?.clone();
|
||||||
Some("Follow") | Some("Announce") | Some("Create") => (),
|
let undone_object =
|
||||||
_ => {
|
AcceptedUndoObjects::from_any_base(any_base)?.ok_or(MyError::ObjectFormat)?;
|
||||||
return Err(MyError::Kind(
|
|
||||||
input.object.kind().unwrap_or("unknown").to_owned(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !input.object.is_kind("Follow") {
|
if !undone_object.is_kind(&UndoTypes::Follow) {
|
||||||
if is_listener {
|
if is_listener {
|
||||||
jobs.queue(Forward::new(input, actor))?;
|
jobs.queue(Forward::new(input, actor))?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else {
|
} else {
|
||||||
return Err(MyError::Kind(
|
return Err(MyError::NotSubscribed(id_string(input.id())?));
|
||||||
input.object.kind().unwrap_or("unknown").to_owned(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let my_id: XsdAnyUri = config.generate_url(UrlKind::Actor).parse()?;
|
let my_id: XsdAnyUri = config.generate_url(UrlKind::Actor).parse()?;
|
||||||
|
|
||||||
if !input.object.child_object_is(&my_id) && !input.object.child_object_is(&public()) {
|
if !undone_object.object_is(&my_id) && !undone_object.object_is(&public()) {
|
||||||
return Err(MyError::WrongActor(input.object.id().to_string()));
|
return Err(MyError::WrongActor(id_string(undone_object.id())?));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !is_listener {
|
if !is_listener {
|
||||||
|
@ -165,7 +186,7 @@ async fn handle_undo(
|
||||||
|
|
||||||
async fn handle_forward(
|
async fn handle_forward(
|
||||||
jobs: &JobServer,
|
jobs: &JobServer,
|
||||||
input: AcceptedObjects,
|
input: AcceptedActivities,
|
||||||
actor: Actor,
|
actor: Actor,
|
||||||
) -> Result<(), MyError> {
|
) -> Result<(), MyError> {
|
||||||
jobs.queue(Forward::new(input, actor))?;
|
jobs.queue(Forward::new(input, actor))?;
|
||||||
|
@ -176,10 +197,10 @@ async fn handle_forward(
|
||||||
async fn handle_announce(
|
async fn handle_announce(
|
||||||
state: &State,
|
state: &State,
|
||||||
jobs: &JobServer,
|
jobs: &JobServer,
|
||||||
input: AcceptedObjects,
|
input: AcceptedActivities,
|
||||||
actor: Actor,
|
actor: Actor,
|
||||||
) -> Result<(), MyError> {
|
) -> Result<(), MyError> {
|
||||||
let object_id = input.object.id();
|
let object_id = input.object().as_single_id().ok_or(MyError::MissingId)?;
|
||||||
|
|
||||||
if state.is_cached(object_id).await {
|
if state.is_cached(object_id).await {
|
||||||
return Err(MyError::Duplicate);
|
return Err(MyError::Duplicate);
|
||||||
|
@ -193,14 +214,16 @@ async fn handle_announce(
|
||||||
async fn handle_follow(
|
async fn handle_follow(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
jobs: &JobServer,
|
jobs: &JobServer,
|
||||||
input: AcceptedObjects,
|
input: AcceptedActivities,
|
||||||
actor: Actor,
|
actor: Actor,
|
||||||
is_listener: bool,
|
is_listener: bool,
|
||||||
) -> Result<(), MyError> {
|
) -> Result<(), MyError> {
|
||||||
let my_id: XsdAnyUri = config.generate_url(UrlKind::Actor).parse()?;
|
let my_id: XsdAnyUri = config.generate_url(UrlKind::Actor).parse()?;
|
||||||
|
|
||||||
if !input.object.is(&my_id) && !input.object.is(&public()) {
|
if !input.object_is(&my_id) && !input.object_is(&public()) {
|
||||||
return Err(MyError::WrongActor(input.object.id().to_string()));
|
return Err(MyError::WrongActor(id_string(
|
||||||
|
input.object().as_single_id(),
|
||||||
|
)?));
|
||||||
}
|
}
|
||||||
|
|
||||||
jobs.queue(Follow::new(is_listener, input, actor))?;
|
jobs.queue(Follow::new(is_listener, input, actor))?;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
@use crate::data::Contact;
|
@use crate::data::Contact;
|
||||||
@use activitystreams::primitives::XsdAnyUri;
|
@use activitystreams_new::primitives::XsdAnyUri;
|
||||||
|
|
||||||
@(contact: &Contact, base: &XsdAnyUri)
|
@(contact: &Contact, base: &XsdAnyUri)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
@use crate::data::Info;
|
@use crate::data::Info;
|
||||||
@use activitystreams::primitives::XsdAnyUri;
|
@use activitystreams_new::primitives::XsdAnyUri;
|
||||||
|
|
||||||
@(info: &Info, base: &XsdAnyUri)
|
@(info: &Info, base: &XsdAnyUri)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
@use crate::{data::{Contact, Instance}, templates::admin};
|
@use crate::{data::{Contact, Instance}, templates::admin};
|
||||||
@use activitystreams::primitives::XsdAnyUri;
|
@use activitystreams_new::primitives::XsdAnyUri;
|
||||||
|
|
||||||
@(instance: &Instance, software: Option<&str>, contact: Option<&Contact>, base: &XsdAnyUri)
|
@(instance: &Instance, software: Option<&str>, contact: Option<&Contact>, base: &XsdAnyUri)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue