Split lemmy_apub crate into two parts apub and apub_receive

This commit is contained in:
Felix Ableitner 2021-03-30 22:23:50 +02:00
parent 36a79e18cd
commit 722cdb78ba
35 changed files with 246 additions and 163 deletions

46
Cargo.lock generated
View file

@ -1802,7 +1802,6 @@ dependencies = [
"background-jobs", "background-jobs",
"base64 0.13.0", "base64 0.13.0",
"bcrypt", "bcrypt",
"captcha",
"chrono", "chrono",
"diesel", "diesel",
"futures", "futures",
@ -1881,6 +1880,50 @@ dependencies = [
"uuid", "uuid",
] ]
[[package]]
name = "lemmy_apub_receive"
version = "0.1.0"
dependencies = [
"activitystreams",
"activitystreams-ext",
"actix",
"actix-rt",
"actix-web",
"anyhow",
"async-trait",
"awc",
"backtrace",
"base64 0.13.0",
"bcrypt",
"chrono",
"diesel",
"futures",
"http",
"http-signature-normalization-actix",
"http-signature-normalization-reqwest",
"itertools",
"lemmy_api_common",
"lemmy_apub",
"lemmy_db_queries",
"lemmy_db_schema",
"lemmy_db_views",
"lemmy_db_views_actor",
"lemmy_utils",
"lemmy_websocket",
"log",
"openssl",
"percent-encoding",
"rand 0.8.3",
"serde",
"serde_json",
"sha2",
"strum",
"strum_macros",
"thiserror",
"tokio 0.3.7",
"url",
]
[[package]] [[package]]
name = "lemmy_db_queries" name = "lemmy_db_queries"
version = "0.1.0" version = "0.1.0"
@ -1996,6 +2039,7 @@ dependencies = [
"lemmy_api_common", "lemmy_api_common",
"lemmy_api_crud", "lemmy_api_crud",
"lemmy_apub", "lemmy_apub",
"lemmy_apub_receive",
"lemmy_db_queries", "lemmy_db_queries",
"lemmy_db_schema", "lemmy_db_schema",
"lemmy_db_views", "lemmy_db_views",

View file

@ -15,6 +15,7 @@ members = [
"crates/api_crud", "crates/api_crud",
"crates/api_common", "crates/api_common",
"crates/apub", "crates/apub",
"crates/apub_receive",
"crates/utils", "crates/utils",
"crates/db_queries", "crates/db_queries",
"crates/db_schema", "crates/db_schema",
@ -29,6 +30,7 @@ members = [
lemmy_api = { path = "./crates/api" } lemmy_api = { path = "./crates/api" }
lemmy_api_crud = { path = "./crates/api_crud" } lemmy_api_crud = { path = "./crates/api_crud" }
lemmy_apub = { path = "./crates/apub" } lemmy_apub = { path = "./crates/apub" }
lemmy_apub_receive = { path = "./crates/apub_receive" }
lemmy_utils = { path = "./crates/utils" } lemmy_utils = { path = "./crates/utils" }
lemmy_db_schema = { path = "./crates/db_schema" } lemmy_db_schema = { path = "./crates/db_schema" }
lemmy_db_queries = { path = "./crates/db_queries" } lemmy_db_queries = { path = "./crates/db_queries" }

View file

@ -38,7 +38,6 @@ itertools = "0.10.0"
uuid = { version = "0.8.2", features = ["serde", "v4"] } uuid = { version = "0.8.2", features = ["serde", "v4"] }
sha2 = "0.9.3" sha2 = "0.9.3"
async-trait = "0.1.42" async-trait = "0.1.42"
captcha = "0.0.8"
anyhow = "1.0.38" anyhow = "1.0.38"
thiserror = "1.0.23" thiserror = "1.0.23"
background-jobs = "0.8.0" background-jobs = "0.8.0"

View file

@ -1,2 +1 @@
pub(crate) mod receive;
pub mod send; pub mod send;

View file

@ -3,7 +3,7 @@ use lemmy_utils::LemmyError;
use serde_json::json; use serde_json::json;
use url::Url; use url::Url;
pub(crate) fn lemmy_context() -> Result<Vec<AnyBase>, LemmyError> { pub fn lemmy_context() -> Result<Vec<AnyBase>, LemmyError> {
let context_ext = AnyBase::from_arbitrary_json(json!( let context_ext = AnyBase::from_arbitrary_json(json!(
{ {
"sc": "http://schema.org#", "sc": "http://schema.org#",

View file

@ -1,5 +1,5 @@
pub(crate) mod context; pub mod context;
pub(crate) mod group_extension; pub(crate) mod group_extension;
pub(crate) mod page_extension; pub(crate) mod page_extension;
pub(crate) mod person_extension; pub(crate) mod person_extension;
pub(crate) mod signatures; pub mod signatures;

View file

@ -26,7 +26,7 @@ lazy_static! {
/// Creates an HTTP post request to `inbox_url`, with the given `client` and `headers`, and /// Creates an HTTP post request to `inbox_url`, with the given `client` and `headers`, and
/// `activity` as request body. The request is signed with `private_key` and then sent. /// `activity` as request body. The request is signed with `private_key` and then sent.
pub async fn sign_and_send( pub(crate) async fn sign_and_send(
client: &Client, client: &Client,
headers: BTreeMap<String, String>, headers: BTreeMap<String, String>,
inbox_url: &Url, inbox_url: &Url,
@ -65,10 +65,7 @@ pub async fn sign_and_send(
} }
/// Verifies the HTTP signature on an incoming inbox request. /// Verifies the HTTP signature on an incoming inbox request.
pub(crate) fn verify_signature( pub fn verify_signature(request: &HttpRequest, actor: &dyn ActorType) -> Result<(), LemmyError> {
request: &HttpRequest,
actor: &dyn ActorType,
) -> Result<(), LemmyError> {
let public_key = actor.public_key().context(location_info!())?; let public_key = actor.public_key().context(location_info!())?;
let verified = CONFIG2 let verified = CONFIG2
.begin_verify( .begin_verify(

View file

@ -5,7 +5,6 @@ use crate::{
person::get_or_fetch_and_upsert_person, person::get_or_fetch_and_upsert_person,
should_refetch_actor, should_refetch_actor,
}, },
inbox::person_inbox::receive_announce,
objects::FromApub, objects::FromApub,
GroupExt, GroupExt,
}; };
@ -31,7 +30,7 @@ use url::Url;
/// ///
/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database. /// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
/// Otherwise it is fetched from the remote instance, stored and returned. /// Otherwise it is fetched from the remote instance, stored and returned.
pub(crate) async fn get_or_fetch_and_upsert_community( pub async fn get_or_fetch_and_upsert_community(
apub_id: &Url, apub_id: &Url,
context: &LemmyContext, context: &LemmyContext,
recursion_counter: &mut i32, recursion_counter: &mut i32,
@ -158,7 +157,8 @@ async fn fetch_community_outbox(
} }
for activity in outbox_activities { for activity in outbox_activities {
receive_announce(context, activity, community, recursion_counter).await?; todo!("{:?} {:?} {:?}", activity, community, recursion_counter);
//receive_announce(context, activity, community, recursion_counter).await?;
} }
Ok(()) Ok(())

View file

@ -1,7 +1,7 @@
pub(crate) mod community; pub mod community;
mod fetch; mod fetch;
pub(crate) mod objects; pub mod objects;
pub(crate) mod person; pub mod person;
pub mod search; pub mod search;
use crate::{ use crate::{
@ -42,7 +42,7 @@ where
/// ///
/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database. /// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
/// Otherwise it is fetched from the remote instance, stored and returned. /// Otherwise it is fetched from the remote instance, stored and returned.
pub(crate) async fn get_or_fetch_and_upsert_actor( pub async fn get_or_fetch_and_upsert_actor(
apub_id: &Url, apub_id: &Url,
context: &LemmyContext, context: &LemmyContext,
recursion_counter: &mut i32, recursion_counter: &mut i32,

View file

@ -13,7 +13,7 @@ use url::Url;
/// pulled from its apub ID, inserted and returned. /// pulled from its apub ID, inserted and returned.
/// ///
/// The parent community is also pulled if necessary. Comments are not pulled. /// The parent community is also pulled if necessary. Comments are not pulled.
pub(crate) async fn get_or_fetch_and_insert_post( pub async fn get_or_fetch_and_insert_post(
post_ap_id: &Url, post_ap_id: &Url,
context: &LemmyContext, context: &LemmyContext,
recursion_counter: &mut i32, recursion_counter: &mut i32,
@ -49,7 +49,7 @@ pub(crate) async fn get_or_fetch_and_insert_post(
/// pulled from its apub ID, inserted and returned. /// pulled from its apub ID, inserted and returned.
/// ///
/// The parent community, post and comment are also pulled if necessary. /// The parent community, post and comment are also pulled if necessary.
pub(crate) async fn get_or_fetch_and_insert_comment( pub async fn get_or_fetch_and_insert_comment(
comment_ap_id: &Url, comment_ap_id: &Url,
context: &LemmyContext, context: &LemmyContext,
recursion_counter: &mut i32, recursion_counter: &mut i32,

View file

@ -17,7 +17,7 @@ use url::Url;
/// ///
/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database. /// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
/// Otherwise it is fetched from the remote instance, stored and returned. /// Otherwise it is fetched from the remote instance, stored and returned.
pub(crate) async fn get_or_fetch_and_upsert_person( pub async fn get_or_fetch_and_upsert_person(
apub_id: &Url, apub_id: &Url,
context: &LemmyContext, context: &LemmyContext,
recursion_counter: &mut i32, recursion_counter: &mut i32,

View file

@ -5,10 +5,7 @@ pub mod activities;
pub mod activity_queue; pub mod activity_queue;
pub mod extensions; pub mod extensions;
pub mod fetcher; pub mod fetcher;
pub mod http;
pub mod inbox;
pub mod objects; pub mod objects;
pub mod routes;
use crate::extensions::{ use crate::extensions::{
group_extension::GroupExtension, group_extension::GroupExtension,
@ -20,7 +17,7 @@ use activitystreams::{
activity::Follow, activity::Follow,
actor, actor,
base::AnyBase, base::AnyBase,
object::{ApObject, Note, Page}, object::{ApObject, AsObject, Note, ObjectExt, Page},
}; };
use activitystreams_ext::{Ext1, Ext2}; use activitystreams_ext::{Ext1, Ext2};
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
@ -36,8 +33,10 @@ use lemmy_db_schema::{
post::Post, post::Post,
private_message::PrivateMessage, private_message::PrivateMessage,
}, },
CommunityId,
DbUrl, DbUrl,
}; };
use lemmy_db_views_actor::community_person_ban_view::CommunityPersonBanView;
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError}; use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use serde::Serialize; use serde::Serialize;
@ -49,8 +48,8 @@ type GroupExt = Ext2<actor::ApActor<ApObject<actor::Group>>, GroupExtension, Pub
/// Activitystreams type for person /// Activitystreams type for person
type PersonExt = Ext2<actor::ApActor<ApObject<actor::Person>>, PersonExtension, PublicKeyExtension>; type PersonExt = Ext2<actor::ApActor<ApObject<actor::Person>>, PersonExtension, PublicKeyExtension>;
/// Activitystreams type for post /// Activitystreams type for post
type PageExt = Ext1<ApObject<Page>, PageExtension>; pub type PageExt = Ext1<ApObject<Page>, PageExtension>;
type NoteExt = ApObject<Note>; pub type NoteExt = ApObject<Note>;
pub static APUB_JSON_CONTENT_TYPE: &str = "application/activity+json"; pub static APUB_JSON_CONTENT_TYPE: &str = "application/activity+json";
@ -63,7 +62,7 @@ pub static APUB_JSON_CONTENT_TYPE: &str = "application/activity+json";
/// - URL not being in the blocklist (if it is active) /// - URL not being in the blocklist (if it is active)
/// ///
/// Note that only one of allowlist and blacklist can be enabled, not both. /// Note that only one of allowlist and blacklist can be enabled, not both.
fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> { pub fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> {
let settings = Settings::get(); let settings = Settings::get();
let domain = apub_id.domain().context(location_info!())?.to_string(); let domain = apub_id.domain().context(location_info!())?.to_string();
let local_instance = settings.get_hostname_without_port()?; let local_instance = settings.get_hostname_without_port()?;
@ -294,13 +293,13 @@ pub fn generate_shared_inbox_url(actor_id: &DbUrl) -> Result<DbUrl, LemmyError>
Ok(Url::parse(&url)?.into()) Ok(Url::parse(&url)?.into())
} }
pub(crate) fn generate_moderators_url(community_id: &DbUrl) -> Result<DbUrl, LemmyError> { pub fn generate_moderators_url(community_id: &DbUrl) -> Result<DbUrl, LemmyError> {
Ok(Url::parse(&format!("{}/moderators", community_id))?.into()) Ok(Url::parse(&format!("{}/moderators", community_id))?.into())
} }
/// Store a sent or received activity in the database, for logging purposes. These records are not /// Store a sent or received activity in the database, for logging purposes. These records are not
/// persistent. /// persistent.
pub(crate) async fn insert_activity<T>( pub async fn insert_activity<T>(
ap_id: &Url, ap_id: &Url,
activity: T, activity: T,
local: bool, local: bool,
@ -318,7 +317,7 @@ where
Ok(()) Ok(())
} }
pub(crate) enum PostOrComment { pub enum PostOrComment {
Comment(Box<Comment>), Comment(Box<Comment>),
Post(Box<Post>), Post(Box<Post>),
} }
@ -326,7 +325,7 @@ pub(crate) enum PostOrComment {
/// Tries to find a post or comment in the local database, without any network requests. /// Tries to find a post or comment in the local database, without any network requests.
/// This is used to handle deletions and removals, because in case we dont have the object, we can /// This is used to handle deletions and removals, because in case we dont have the object, we can
/// simply ignore the activity. /// simply ignore the activity.
pub(crate) async fn find_post_or_comment_by_id( pub async fn find_post_or_comment_by_id(
context: &LemmyContext, context: &LemmyContext,
apub_id: Url, apub_id: Url,
) -> Result<PostOrComment, LemmyError> { ) -> Result<PostOrComment, LemmyError> {
@ -400,3 +399,49 @@ pub(crate) async fn find_object_by_id(
Err(NotFound.into()) Err(NotFound.into())
} }
pub async fn check_community_or_site_ban(
person: &Person,
community_id: CommunityId,
pool: &DbPool,
) -> Result<(), LemmyError> {
if person.banned {
return Err(anyhow!("Person is banned from site").into());
}
let person_id = person.id;
let is_banned =
move |conn: &'_ _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok();
if blocking(pool, is_banned).await? {
return Err(anyhow!("Person is banned from community").into());
}
Ok(())
}
pub fn get_activity_to_and_cc<T, Kind>(activity: &T) -> Vec<Url>
where
T: AsObject<Kind>,
{
let mut to_and_cc = vec![];
if let Some(to) = activity.to() {
let to = to.to_owned().unwrap_to_vec();
let mut to = to
.iter()
.map(|t| t.as_xsd_any_uri())
.flatten()
.map(|t| t.to_owned())
.collect();
to_and_cc.append(&mut to);
}
if let Some(cc) = activity.cc() {
let cc = cc.to_owned().unwrap_to_vec();
let mut cc = cc
.iter()
.map(|c| c.as_xsd_any_uri())
.flatten()
.map(|c| c.to_owned())
.collect();
to_and_cc.append(&mut cc);
}
to_and_cc
}

View file

@ -1,7 +1,8 @@
use crate::{ use crate::{
check_community_or_site_ban,
check_is_apub_id_valid, check_is_apub_id_valid,
fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person}, fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person},
inbox::{community_inbox::check_community_or_site_ban, get_activity_to_and_cc}, get_activity_to_and_cc,
PageExt, PageExt,
}; };
use activitystreams::{ use activitystreams::{
@ -33,14 +34,14 @@ pub(crate) mod private_message;
/// Trait for converting an object or actor into the respective ActivityPub type. /// Trait for converting an object or actor into the respective ActivityPub type.
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
pub(crate) trait ToApub { pub trait ToApub {
type ApubType; type ApubType;
async fn to_apub(&self, pool: &DbPool) -> Result<Self::ApubType, LemmyError>; async fn to_apub(&self, pool: &DbPool) -> Result<Self::ApubType, LemmyError>;
fn to_tombstone(&self) -> Result<Tombstone, LemmyError>; fn to_tombstone(&self) -> Result<Tombstone, LemmyError>;
} }
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
pub(crate) trait FromApub { pub trait FromApub {
type ApubType; type ApubType;
/// Converts an object from ActivityPub type to Lemmy internal type. /// Converts an object from ActivityPub type to Lemmy internal type.
/// ///

View file

@ -0,0 +1,45 @@
[package]
name = "lemmy_apub_receive"
version = "0.1.0"
edition = "2018"
[dependencies]
lemmy_utils = { path = "../utils" }
lemmy_apub = { path = "../apub" }
lemmy_db_queries = { path = "../db_queries" }
lemmy_db_schema = { path = "../db_schema" }
lemmy_db_views = { path = "../db_views" }
lemmy_db_views_actor = { path = "../db_views_actor" }
lemmy_api_common = { path = "../api_common" }
lemmy_websocket = { path = "../websocket" }
diesel = "1.4.5"
activitystreams = "0.7.0-alpha.11"
activitystreams-ext = "0.1.0-alpha.2"
bcrypt = "0.9.0"
chrono = { version = "0.4.19", features = ["serde"] }
serde_json = { version = "1.0.61", features = ["preserve_order"] }
serde = { version = "1.0.123", features = ["derive"] }
actix = "0.10.0"
actix-web = { version = "3.3.2", default-features = false }
actix-rt = { version = "1.1.1", default-features = false }
awc = { version = "2.0.3", default-features = false }
log = "0.4.14"
rand = "0.8.3"
strum = "0.20.0"
strum_macros = "0.20.1"
url = { version = "2.2.1", features = ["serde"] }
percent-encoding = "2.1.0"
openssl = "0.10.32"
http = "0.2.3"
http-signature-normalization-actix = { version = "0.4.1", default-features = false, features = ["sha-2"] }
http-signature-normalization-reqwest = { version = "0.1.3", default-features = false, features = ["sha-2"] }
base64 = "0.13.0"
tokio = "0.3.6"
futures = "0.3.12"
itertools = "0.10.0"
sha2 = "0.9.3"
async-trait = "0.1.42"
anyhow = "1.0.38"
thiserror = "1.0.23"
backtrace = "0.3.56"

View file

@ -0,0 +1 @@
pub(crate) mod receive;

View file

@ -1,10 +1,11 @@
use crate::{activities::receive::get_actor_as_person, objects::FromApub, ActorType, NoteExt}; use crate::activities::receive::get_actor_as_person;
use activitystreams::{ use activitystreams::{
activity::{ActorAndObjectRefExt, Create, Dislike, Like, Update}, activity::{ActorAndObjectRefExt, Create, Dislike, Like, Update},
base::ExtendsExt, base::ExtendsExt,
}; };
use anyhow::Context; use anyhow::Context;
use lemmy_api_common::{blocking, comment::CommentResponse, send_local_notifs}; use lemmy_api_common::{blocking, comment::CommentResponse, send_local_notifs};
use lemmy_apub::{objects::FromApub, ActorType, NoteExt};
use lemmy_db_queries::{source::comment::Comment_, Crud, Likeable}; use lemmy_db_queries::{source::comment::Comment_, Crud, Likeable};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
comment::{Comment, CommentLike, CommentLikeForm}, comment::{Comment, CommentLike, CommentLikeForm},

View file

@ -1,10 +1,10 @@
use crate::fetcher::person::get_or_fetch_and_upsert_person;
use activitystreams::{ use activitystreams::{
activity::{ActorAndObjectRef, ActorAndObjectRefExt}, activity::{ActorAndObjectRef, ActorAndObjectRefExt},
base::{AsBase, BaseExt}, base::{AsBase, BaseExt},
error::DomainError, error::DomainError,
}; };
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use lemmy_apub::fetcher::person::get_or_fetch_and_upsert_person;
use lemmy_db_schema::source::person::Person; use lemmy_db_schema::source::person::Person;
use lemmy_utils::{location_info, LemmyError}; use lemmy_utils::{location_info, LemmyError};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;

View file

@ -1,9 +1,6 @@
use crate::{ use crate::{
activities::receive::get_actor_as_person, activities::receive::get_actor_as_person,
inbox::receive_for_community::verify_mod_activity, inbox::receive_for_community::verify_mod_activity,
objects::FromApub,
ActorType,
PageExt,
}; };
use activitystreams::{ use activitystreams::{
activity::{Announce, Create, Dislike, Like, Update}, activity::{Announce, Create, Dislike, Like, Update},
@ -11,6 +8,7 @@ use activitystreams::{
}; };
use anyhow::Context; use anyhow::Context;
use lemmy_api_common::{blocking, post::PostResponse}; use lemmy_api_common::{blocking, post::PostResponse};
use lemmy_apub::{objects::FromApub, ActorType, PageExt};
use lemmy_db_queries::{source::post::Post_, ApubObject, Crud, Likeable}; use lemmy_db_queries::{source::post::Post_, ApubObject, Crud, Likeable};
use lemmy_db_schema::{ use lemmy_db_schema::{
source::{ source::{

View file

@ -1,11 +1,4 @@
use crate::{ use crate::activities::receive::verify_activity_domains_valid;
activities::receive::verify_activity_domains_valid,
check_is_apub_id_valid,
fetcher::person::get_or_fetch_and_upsert_person,
inbox::get_activity_to_and_cc,
objects::FromApub,
NoteExt,
};
use activitystreams::{ use activitystreams::{
activity::{ActorAndObjectRefExt, Create, Delete, Undo, Update}, activity::{ActorAndObjectRefExt, Create, Delete, Undo, Update},
base::{AsBase, ExtendsExt}, base::{AsBase, ExtendsExt},
@ -14,6 +7,13 @@ use activitystreams::{
}; };
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use lemmy_api_common::{blocking, person::PrivateMessageResponse}; use lemmy_api_common::{blocking, person::PrivateMessageResponse};
use lemmy_apub::{
check_is_apub_id_valid,
fetcher::person::get_or_fetch_and_upsert_person,
get_activity_to_and_cc,
objects::FromApub,
NoteExt,
};
use lemmy_db_queries::source::private_message::PrivateMessage_; use lemmy_db_queries::source::private_message::PrivateMessage_;
use lemmy_db_schema::source::private_message::PrivateMessage; use lemmy_db_schema::source::private_message::PrivateMessage;
use lemmy_db_views::{local_user_view::LocalUserView, private_message_view::PrivateMessageView}; use lemmy_db_views::{local_user_view::LocalUserView, private_message_view::PrivateMessageView};

View file

@ -1,10 +1,8 @@
use crate::{ use crate::http::{create_apub_response, create_apub_tombstone_response};
http::{create_apub_response, create_apub_tombstone_response},
objects::ToApub,
};
use actix_web::{body::Body, web, web::Path, HttpResponse}; use actix_web::{body::Body, web, web::Path, HttpResponse};
use diesel::result::Error::NotFound; use diesel::result::Error::NotFound;
use lemmy_api_common::blocking; use lemmy_api_common::blocking;
use lemmy_apub::objects::ToApub;
use lemmy_db_queries::Crud; use lemmy_db_queries::Crud;
use lemmy_db_schema::{source::comment::Comment, CommentId}; use lemmy_db_schema::{source::comment::Comment, CommentId};
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;

View file

@ -1,10 +1,4 @@
use crate::{ use crate::http::{create_apub_response, create_apub_tombstone_response};
extensions::context::lemmy_context,
generate_moderators_url,
http::{create_apub_response, create_apub_tombstone_response},
objects::ToApub,
ActorType,
};
use activitystreams::{ use activitystreams::{
base::{AnyBase, BaseExt}, base::{AnyBase, BaseExt},
collection::{CollectionExt, OrderedCollection, UnorderedCollection}, collection::{CollectionExt, OrderedCollection, UnorderedCollection},
@ -12,6 +6,12 @@ use activitystreams::{
}; };
use actix_web::{body::Body, web, HttpResponse}; use actix_web::{body::Body, web, HttpResponse};
use lemmy_api_common::blocking; use lemmy_api_common::blocking;
use lemmy_apub::{
extensions::context::lemmy_context,
generate_moderators_url,
objects::ToApub,
ActorType,
};
use lemmy_db_queries::source::{activity::Activity_, community::Community_}; use lemmy_db_queries::source::{activity::Activity_, community::Community_};
use lemmy_db_schema::source::{activity::Activity, community::Community}; use lemmy_db_schema::source::{activity::Activity, community::Community};
use lemmy_db_views_actor::{ use lemmy_db_views_actor::{

View file

@ -1,7 +1,7 @@
use crate::APUB_JSON_CONTENT_TYPE;
use actix_web::{body::Body, web, HttpResponse}; use actix_web::{body::Body, web, HttpResponse};
use http::StatusCode; use http::StatusCode;
use lemmy_api_common::blocking; use lemmy_api_common::blocking;
use lemmy_apub::APUB_JSON_CONTENT_TYPE;
use lemmy_db_queries::source::activity::Activity_; use lemmy_db_queries::source::activity::Activity_;
use lemmy_db_schema::source::activity::Activity; use lemmy_db_schema::source::activity::Activity;
use lemmy_utils::{settings::structs::Settings, LemmyError}; use lemmy_utils::{settings::structs::Settings, LemmyError};

View file

@ -1,15 +1,11 @@
use crate::{ use crate::http::{create_apub_response, create_apub_tombstone_response};
extensions::context::lemmy_context,
http::{create_apub_response, create_apub_tombstone_response},
objects::ToApub,
ActorType,
};
use activitystreams::{ use activitystreams::{
base::BaseExt, base::BaseExt,
collection::{CollectionExt, OrderedCollection}, collection::{CollectionExt, OrderedCollection},
}; };
use actix_web::{body::Body, web, HttpResponse}; use actix_web::{body::Body, web, HttpResponse};
use lemmy_api_common::blocking; use lemmy_api_common::blocking;
use lemmy_apub::{extensions::context::lemmy_context, objects::ToApub, ActorType};
use lemmy_db_queries::source::person::Person_; use lemmy_db_queries::source::person::Person_;
use lemmy_db_schema::source::person::Person; use lemmy_db_schema::source::person::Person;
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;

View file

@ -1,10 +1,8 @@
use crate::{ use crate::http::{create_apub_response, create_apub_tombstone_response};
http::{create_apub_response, create_apub_tombstone_response},
objects::ToApub,
};
use actix_web::{body::Body, web, HttpResponse}; use actix_web::{body::Body, web, HttpResponse};
use diesel::result::Error::NotFound; use diesel::result::Error::NotFound;
use lemmy_api_common::blocking; use lemmy_api_common::blocking;
use lemmy_apub::objects::ToApub;
use lemmy_db_queries::Crud; use lemmy_db_queries::Crud;
use lemmy_db_schema::{source::post::Post, PostId}; use lemmy_db_schema::{source::post::Post, PostId};
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;

View file

@ -3,7 +3,6 @@ use crate::{
inbox::{ inbox::{
assert_activity_not_local, assert_activity_not_local,
get_activity_id, get_activity_id,
get_activity_to_and_cc,
inbox_verify_http_signature, inbox_verify_http_signature,
is_activity_already_known, is_activity_already_known,
receive_for_community::{ receive_for_community::{
@ -18,9 +17,6 @@ use crate::{
}, },
verify_is_addressed_to_public, verify_is_addressed_to_public,
}, },
insert_activity,
ActorType,
CommunityType,
}; };
use activitystreams::{ use activitystreams::{
activity::{kind::FollowType, ActorAndObject, Follow, Undo}, activity::{kind::FollowType, ActorAndObject, Follow, Undo},
@ -30,15 +26,18 @@ use activitystreams::{
use actix_web::{web, HttpRequest, HttpResponse}; use actix_web::{web, HttpRequest, HttpResponse};
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use lemmy_api_common::blocking; use lemmy_api_common::blocking;
use lemmy_db_queries::{source::community::Community_, ApubObject, DbPool, Followable}; use lemmy_apub::{
use lemmy_db_schema::{ check_community_or_site_ban,
source::{ get_activity_to_and_cc,
community::{Community, CommunityFollower, CommunityFollowerForm}, insert_activity,
person::Person, ActorType,
}, CommunityType,
CommunityId, };
use lemmy_db_queries::{source::community::Community_, ApubObject, Followable};
use lemmy_db_schema::source::{
community::{Community, CommunityFollower, CommunityFollowerForm},
person::Person,
}; };
use lemmy_db_views_actor::community_person_ban_view::CommunityPersonBanView;
use lemmy_utils::{location_info, LemmyError}; use lemmy_utils::{location_info, LemmyError};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use log::info; use log::info;
@ -318,21 +317,3 @@ async fn handle_undo_follow(
Ok(()) Ok(())
} }
pub(crate) async fn check_community_or_site_ban(
person: &Person,
community_id: CommunityId,
pool: &DbPool,
) -> Result<(), LemmyError> {
if person.banned {
return Err(anyhow!("Person is banned from site").into());
}
let person_id = person.id;
let is_banned =
move |conn: &'_ _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok();
if blocking(pool, is_banned).await? {
return Err(anyhow!("Person is banned from community").into());
}
Ok(())
}

View file

@ -1,18 +1,19 @@
use crate::{
check_is_apub_id_valid,
extensions::signatures::verify_signature,
fetcher::get_or_fetch_and_upsert_actor,
ActorType,
};
use activitystreams::{ use activitystreams::{
activity::ActorAndObjectRefExt, activity::ActorAndObjectRefExt,
base::{AsBase, BaseExt, Extends}, base::{AsBase, BaseExt, Extends},
object::{AsObject, ObjectExt}, object::AsObject,
public, public,
}; };
use actix_web::HttpRequest; use actix_web::HttpRequest;
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use lemmy_api_common::blocking; use lemmy_api_common::blocking;
use lemmy_apub::{
check_is_apub_id_valid,
extensions::signatures::verify_signature,
fetcher::get_or_fetch_and_upsert_actor,
get_activity_to_and_cc,
ActorType,
};
use lemmy_db_queries::{ use lemmy_db_queries::{
source::{activity::Activity_, community::Community_}, source::{activity::Activity_, community::Community_},
ApubObject, ApubObject,
@ -56,34 +57,6 @@ pub(crate) async fn is_activity_already_known(
} }
} }
pub(crate) fn get_activity_to_and_cc<T, Kind>(activity: &T) -> Vec<Url>
where
T: AsObject<Kind>,
{
let mut to_and_cc = vec![];
if let Some(to) = activity.to() {
let to = to.to_owned().unwrap_to_vec();
let mut to = to
.iter()
.map(|t| t.as_xsd_any_uri())
.flatten()
.map(|t| t.to_owned())
.collect();
to_and_cc.append(&mut to);
}
if let Some(cc) = activity.cc() {
let cc = cc.to_owned().unwrap_to_vec();
let mut cc = cc
.iter()
.map(|c| c.as_xsd_any_uri())
.flatten()
.map(|c| c.to_owned())
.collect();
to_and_cc.append(&mut cc);
}
to_and_cc
}
pub(crate) fn verify_is_addressed_to_public<T, Kind>(activity: &T) -> Result<(), LemmyError> pub(crate) fn verify_is_addressed_to_public<T, Kind>(activity: &T) -> Result<(), LemmyError>
where where
T: AsBase<Kind> + AsObject<Kind> + ActorAndObjectRefExt, T: AsBase<Kind> + AsObject<Kind> + ActorAndObjectRefExt,

View file

@ -16,12 +16,9 @@ use crate::{
receive_unhandled_activity, receive_unhandled_activity,
verify_activity_domains_valid, verify_activity_domains_valid,
}, },
check_is_apub_id_valid,
fetcher::community::get_or_fetch_and_upsert_community,
inbox::{ inbox::{
assert_activity_not_local, assert_activity_not_local,
get_activity_id, get_activity_id,
get_activity_to_and_cc,
inbox_verify_http_signature, inbox_verify_http_signature,
is_activity_already_known, is_activity_already_known,
is_addressed_to_community_followers, is_addressed_to_community_followers,
@ -38,8 +35,6 @@ use crate::{
}, },
verify_is_addressed_to_public, verify_is_addressed_to_public,
}, },
insert_activity,
ActorType,
}; };
use activitystreams::{ use activitystreams::{
activity::{Accept, ActorAndObject, Announce, Create, Delete, Follow, Remove, Undo, Update}, activity::{Accept, ActorAndObject, Announce, Create, Delete, Follow, Remove, Undo, Update},
@ -50,6 +45,13 @@ use actix_web::{web, HttpRequest, HttpResponse};
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use diesel::NotFound; use diesel::NotFound;
use lemmy_api_common::blocking; use lemmy_api_common::blocking;
use lemmy_apub::{
check_is_apub_id_valid,
fetcher::community::get_or_fetch_and_upsert_community,
get_activity_to_and_cc,
insert_activity,
ActorType,
};
use lemmy_db_queries::{source::person::Person_, ApubObject, Followable}; use lemmy_db_queries::{source::person::Person_, ApubObject, Followable};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
community::{Community, CommunityFollower}, community::{Community, CommunityFollower},

View file

@ -31,15 +31,7 @@ use crate::{
receive_unhandled_activity, receive_unhandled_activity,
verify_activity_domains_valid, verify_activity_domains_valid,
}, },
fetcher::{
objects::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
person::get_or_fetch_and_upsert_person,
},
find_post_or_comment_by_id,
generate_moderators_url,
inbox::verify_is_addressed_to_public, inbox::verify_is_addressed_to_public,
CommunityType,
PostOrComment,
}; };
use activitystreams::{ use activitystreams::{
activity::{ activity::{
@ -62,6 +54,16 @@ use activitystreams::{
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use diesel::result::Error::NotFound; use diesel::result::Error::NotFound;
use lemmy_api_common::blocking; use lemmy_api_common::blocking;
use lemmy_apub::{
fetcher::{
objects::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
person::get_or_fetch_and_upsert_person,
},
find_post_or_comment_by_id,
generate_moderators_url,
CommunityType,
PostOrComment,
};
use lemmy_db_queries::{source::community::CommunityModerator_, ApubObject, Crud, Joinable}; use lemmy_db_queries::{source::community::CommunityModerator_, ApubObject, Crud, Joinable};
use lemmy_db_schema::{ use lemmy_db_schema::{
source::{ source::{

View file

@ -1,21 +1,18 @@
use crate::{ use crate::inbox::{
inbox::{ assert_activity_not_local,
assert_activity_not_local, community_inbox::{community_receive_message, CommunityAcceptedActivities},
community_inbox::{community_receive_message, CommunityAcceptedActivities}, get_activity_id,
get_activity_id, inbox_verify_http_signature,
get_activity_to_and_cc, is_activity_already_known,
inbox_verify_http_signature, is_addressed_to_community_followers,
is_activity_already_known, is_addressed_to_local_person,
is_addressed_to_community_followers, person_inbox::{person_receive_message, PersonAcceptedActivities},
is_addressed_to_local_person,
person_inbox::{person_receive_message, PersonAcceptedActivities},
},
insert_activity,
}; };
use activitystreams::{activity::ActorAndObject, prelude::*}; use activitystreams::{activity::ActorAndObject, prelude::*};
use actix_web::{web, HttpRequest, HttpResponse}; use actix_web::{web, HttpRequest, HttpResponse};
use anyhow::Context; use anyhow::Context;
use lemmy_api_common::blocking; use lemmy_api_common::blocking;
use lemmy_apub::{get_activity_to_and_cc, insert_activity};
use lemmy_db_queries::{ApubObject, DbPool}; use lemmy_db_queries::{ApubObject, DbPool};
use lemmy_db_schema::source::community::Community; use lemmy_db_schema::source::community::Community;
use lemmy_utils::{location_info, LemmyError}; use lemmy_utils::{location_info, LemmyError};

View file

@ -0,0 +1,4 @@
mod activities;
mod http;
mod inbox;
pub mod routes;

View file

@ -17,10 +17,10 @@ use crate::{
person_inbox::person_inbox, person_inbox::person_inbox,
shared_inbox::shared_inbox, shared_inbox::shared_inbox,
}, },
APUB_JSON_CONTENT_TYPE,
}; };
use actix_web::*; use actix_web::*;
use http_signature_normalization_actix::digest::middleware::VerifyDigest; use http_signature_normalization_actix::digest::middleware::VerifyDigest;
use lemmy_apub::APUB_JSON_CONTENT_TYPE;
use lemmy_utils::settings::structs::Settings; use lemmy_utils::settings::structs::Settings;
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};

View file

@ -91,7 +91,7 @@ async fn main() -> Result<(), LemmyError> {
.data(context) .data(context)
// The routes // The routes
.configure(|cfg| api_routes::config(cfg, &rate_limiter)) .configure(|cfg| api_routes::config(cfg, &rate_limiter))
.configure(lemmy_apub::routes::config) .configure(lemmy_apub_receive::routes::config)
.configure(feeds::config) .configure(feeds::config)
.configure(|cfg| images::config(cfg, &rate_limiter)) .configure(|cfg| images::config(cfg, &rate_limiter))
.configure(nodeinfo::config) .configure(nodeinfo::config)