Rename ImportError to HandlerError

This commit is contained in:
silverpill 2022-10-23 22:18:01 +00:00
parent 1e575b2f6f
commit 256e225742
9 changed files with 82 additions and 77 deletions

View file

@ -3,16 +3,18 @@ use std::path::Path;
use tokio_postgres::GenericClient; use tokio_postgres::GenericClient;
use crate::activitypub::activity::Object; use crate::activitypub::{
use crate::activitypub::actors::types::{Actor, ActorAddress}; activity::Object,
use crate::activitypub::handlers::{ actors::types::{Actor, ActorAddress},
handlers::{
create_note::handle_note, create_note::handle_note,
update_person::update_remote_profile, update_person::update_remote_profile,
},
identifiers::parse_local_object_id,
receiver::HandlerError,
}; };
use crate::activitypub::identifiers::parse_local_object_id;
use crate::config::{Config, Instance}; use crate::config::{Config, Instance};
use crate::errors::{DatabaseError, HttpError, ValidationError}; use crate::errors::{DatabaseError, ValidationError};
use crate::http_signatures::verify::VerificationError;
use crate::models::posts::queries::{ use crate::models::posts::queries::{
get_post_by_id, get_post_by_id,
get_post_by_remote_object_id, get_post_by_remote_object_id,
@ -29,52 +31,17 @@ use super::fetchers::{
fetch_actor_images, fetch_actor_images,
fetch_object, fetch_object,
perform_webfinger_query, perform_webfinger_query,
FetchError,
}; };
#[derive(thiserror::Error, Debug)]
pub enum ImportError {
#[error("local object")]
LocalObject,
#[error(transparent)]
FetchError(#[from] FetchError),
#[error(transparent)]
ValidationError(#[from] ValidationError),
#[error(transparent)]
DatabaseError(#[from] DatabaseError),
#[error(transparent)]
AuthError(#[from] VerificationError),
}
impl From<ImportError> for HttpError {
fn from(error: ImportError) -> Self {
match error {
ImportError::LocalObject => HttpError::InternalError,
ImportError::FetchError(error) => {
HttpError::ValidationError(error.to_string())
},
ImportError::ValidationError(error) => error.into(),
ImportError::DatabaseError(error) => error.into(),
ImportError::AuthError(_) => {
HttpError::AuthError("invalid signature")
},
}
}
}
async fn create_remote_profile( async fn create_remote_profile(
db_client: &impl GenericClient, db_client: &impl GenericClient,
instance: &Instance, instance: &Instance,
media_dir: &Path, media_dir: &Path,
actor: Actor, actor: Actor,
) -> Result<DbActorProfile, ImportError> { ) -> Result<DbActorProfile, HandlerError> {
let actor_address = actor.address()?; let actor_address = actor.address()?;
if actor_address.is_local(&instance.host()) { if actor_address.is_local(&instance.host()) {
return Err(ImportError::LocalObject); return Err(HandlerError::LocalObject);
}; };
let maybe_also_known_as = actor.also_known_as.as_ref() let maybe_also_known_as = actor.also_known_as.as_ref()
.and_then(|aliases| aliases.first()); .and_then(|aliases| aliases.first());
@ -112,9 +79,9 @@ pub async fn get_or_import_profile_by_actor_id(
instance: &Instance, instance: &Instance,
media_dir: &Path, media_dir: &Path,
actor_id: &str, actor_id: &str,
) -> Result<DbActorProfile, ImportError> { ) -> Result<DbActorProfile, HandlerError> {
if actor_id.starts_with(&instance.url()) { if actor_id.starts_with(&instance.url()) {
return Err(ImportError::LocalObject); return Err(HandlerError::LocalObject);
}; };
let profile = match get_profile_by_remote_actor_id( let profile = match get_profile_by_remote_actor_id(
db_client, db_client,
@ -188,9 +155,9 @@ pub async fn import_profile_by_actor_address(
instance: &Instance, instance: &Instance,
media_dir: &Path, media_dir: &Path,
actor_address: &ActorAddress, actor_address: &ActorAddress,
) -> Result<DbActorProfile, ImportError> { ) -> Result<DbActorProfile, HandlerError> {
if actor_address.hostname == instance.host() { if actor_address.hostname == instance.host() {
return Err(ImportError::LocalObject); return Err(HandlerError::LocalObject);
}; };
let actor_id = perform_webfinger_query(instance, actor_address).await?; let actor_id = perform_webfinger_query(instance, actor_address).await?;
let actor = fetch_actor(instance, &actor_id).await?; let actor = fetch_actor(instance, &actor_id).await?;
@ -218,11 +185,11 @@ pub async fn import_post(
db_client: &mut impl GenericClient, db_client: &mut impl GenericClient,
object_id: String, object_id: String,
object_received: Option<Object>, object_received: Option<Object>,
) -> Result<Post, ImportError> { ) -> Result<Post, HandlerError> {
let instance = config.instance(); let instance = config.instance();
let media_dir = config.media_dir(); let media_dir = config.media_dir();
if parse_local_object_id(&instance.url(), &object_id).is_ok() { if parse_local_object_id(&instance.url(), &object_id).is_ok() {
return Err(ImportError::LocalObject); return Err(HandlerError::LocalObject);
}; };
let mut queue = vec![object_id]; // LIFO queue let mut queue = vec![object_id]; // LIFO queue

View file

@ -2,7 +2,6 @@ use tokio_postgres::GenericClient;
use crate::activitypub::{ use crate::activitypub::{
activity::Activity, activity::Activity,
fetcher::helpers::ImportError,
identifiers::parse_local_actor_id, identifiers::parse_local_actor_id,
receiver::find_object_id, receiver::find_object_id,
vocabulary::PERSON, vocabulary::PERSON,
@ -12,7 +11,7 @@ use crate::errors::ValidationError;
use crate::models::profiles::queries::get_profile_by_remote_actor_id; use crate::models::profiles::queries::get_profile_by_remote_actor_id;
use crate::models::relationships::queries::subscribe_opt; use crate::models::relationships::queries::subscribe_opt;
use crate::models::users::queries::get_user_by_name; use crate::models::users::queries::get_user_by_name;
use super::HandlerResult; use super::{HandlerError, HandlerResult};
pub async fn handle_add( pub async fn handle_add(
config: &Config, config: &Config,
@ -23,7 +22,7 @@ pub async fn handle_add(
db_client, db_client,
&activity.actor, &activity.actor,
).await?; ).await?;
let actor = actor_profile.actor_json.ok_or(ImportError::LocalObject)?; let actor = actor_profile.actor_json.ok_or(HandlerError::LocalObject)?;
let target_value = activity.target.ok_or(ValidationError("target is missing"))?; let target_value = activity.target.ok_or(ValidationError("target is missing"))?;
let target_id = find_object_id(&target_value)?; let target_id = find_object_id(&target_value)?;
if Some(target_id) == actor.subscribers { if Some(target_id) == actor.subscribers {

View file

@ -13,10 +13,9 @@ use crate::activitypub::{
fetcher::helpers::{ fetcher::helpers::{
get_or_import_profile_by_actor_id, get_or_import_profile_by_actor_id,
import_profile_by_actor_address, import_profile_by_actor_address,
ImportError,
}, },
identifiers::parse_local_actor_id, identifiers::parse_local_actor_id,
receiver::{parse_array, parse_property_value}, receiver::{parse_array, parse_property_value, HandlerError},
vocabulary::{DOCUMENT, HASHTAG, IMAGE, LINK, MENTION, NOTE}, vocabulary::{DOCUMENT, HASHTAG, IMAGE, LINK, MENTION, NOTE},
}; };
use crate::config::Instance; use crate::config::Instance;
@ -125,7 +124,7 @@ pub async fn handle_note(
media_dir: &Path, media_dir: &Path,
object: Object, object: Object,
redirects: &HashMap<String, String>, redirects: &HashMap<String, String>,
) -> Result<Post, ImportError> { ) -> Result<Post, HandlerError> {
if object.object_type != NOTE { if object.object_type != NOTE {
// Could be Page (in Lemmy) or some other type // Could be Page (in Lemmy) or some other type
log::warn!("processing object of type {}", object.object_type); log::warn!("processing object of type {}", object.object_type);
@ -267,7 +266,7 @@ pub async fn handle_note(
&actor_address, &actor_address,
).await { ).await {
Ok(profile) => profile, Ok(profile) => profile,
Err(ImportError::FetchError(error)) => { Err(HandlerError::FetchError(error)) => {
// Ignore mention if fetcher fails // Ignore mention if fetcher fails
log::warn!( log::warn!(
"failed to find mentioned profile {}: {}", "failed to find mentioned profile {}: {}",

View file

@ -3,7 +3,7 @@ use tokio_postgres::GenericClient;
use crate::activitypub::{ use crate::activitypub::{
activity::Activity, activity::Activity,
builders::accept_follow::prepare_accept_follow, builders::accept_follow::prepare_accept_follow,
fetcher::helpers::{get_or_import_profile_by_actor_id, ImportError}, fetcher::helpers::get_or_import_profile_by_actor_id,
identifiers::parse_local_actor_id, identifiers::parse_local_actor_id,
receiver::find_object_id, receiver::find_object_id,
vocabulary::PERSON, vocabulary::PERSON,
@ -12,7 +12,7 @@ use crate::config::Config;
use crate::errors::DatabaseError; use crate::errors::DatabaseError;
use crate::models::relationships::queries::follow; use crate::models::relationships::queries::follow;
use crate::models::users::queries::get_user_by_name; use crate::models::users::queries::get_user_by_name;
use super::HandlerResult; use super::{HandlerError, HandlerResult};
pub async fn handle_follow( pub async fn handle_follow(
config: &Config, config: &Config,
@ -26,7 +26,7 @@ pub async fn handle_follow(
&activity.actor, &activity.actor,
).await?; ).await?;
let source_actor = source_profile.actor_json let source_actor = source_profile.actor_json
.ok_or(ImportError::LocalObject)?; .ok_or(HandlerError::LocalObject)?;
let target_actor_id = find_object_id(&activity.object)?; let target_actor_id = find_object_id(&activity.object)?;
let target_username = parse_local_actor_id( let target_username = parse_local_actor_id(
&config.instance_url(), &config.instance_url(),

View file

@ -1,7 +1,7 @@
use super::fetcher::helpers::ImportError; pub use super::receiver::HandlerError;
// Handlers should return object type if activity has been accepted // Handlers should return object type if activity has been accepted
// or None if it has been ignored // or None if it has been ignored
pub type HandlerResult = Result<Option<&'static str>, ImportError>; pub type HandlerResult = Result<Option<&'static str>, HandlerError>;
pub mod accept_follow; pub mod accept_follow;
pub mod add; pub mod add;

View file

@ -2,7 +2,6 @@ use tokio_postgres::GenericClient;
use crate::activitypub::{ use crate::activitypub::{
activity::Activity, activity::Activity,
fetcher::helpers::ImportError,
identifiers::parse_local_actor_id, identifiers::parse_local_actor_id,
receiver::find_object_id, receiver::find_object_id,
vocabulary::PERSON, vocabulary::PERSON,
@ -15,7 +14,7 @@ use crate::models::notifications::queries::{
use crate::models::profiles::queries::get_profile_by_remote_actor_id; use crate::models::profiles::queries::get_profile_by_remote_actor_id;
use crate::models::relationships::queries::unsubscribe; use crate::models::relationships::queries::unsubscribe;
use crate::models::users::queries::get_user_by_name; use crate::models::users::queries::get_user_by_name;
use super::HandlerResult; use super::{HandlerError, HandlerResult};
pub async fn handle_remove( pub async fn handle_remove(
config: &Config, config: &Config,
@ -26,7 +25,7 @@ pub async fn handle_remove(
db_client, db_client,
&activity.actor, &activity.actor,
).await?; ).await?;
let actor = actor_profile.actor_json.ok_or(ImportError::LocalObject)?; let actor = actor_profile.actor_json.ok_or(HandlerError::LocalObject)?;
let target_value = activity.target.ok_or(ValidationError("target is missing"))?; let target_value = activity.target.ok_or(ValidationError("target is missing"))?;
let target_id = find_object_id(&target_value)?; let target_id = find_object_id(&target_value)?;
if Some(target_id) == actor.subscribers { if Some(target_id) == actor.subscribers {

View file

@ -6,7 +6,6 @@ use crate::activitypub::{
activity::Activity, activity::Activity,
actors::types::Actor, actors::types::Actor,
fetcher::fetchers::fetch_actor_images, fetcher::fetchers::fetch_actor_images,
fetcher::helpers::ImportError,
vocabulary::PERSON, vocabulary::PERSON,
}; };
use crate::config::{Config, Instance}; use crate::config::{Config, Instance};
@ -16,7 +15,7 @@ use crate::models::profiles::queries::{
update_profile, update_profile,
}; };
use crate::models::profiles::types::{DbActorProfile, ProfileUpdateData}; use crate::models::profiles::types::{DbActorProfile, ProfileUpdateData};
use super::HandlerResult; use super::{HandlerError, HandlerResult};
pub async fn handle_update_person( pub async fn handle_update_person(
config: &Config, config: &Config,
@ -49,8 +48,8 @@ pub async fn update_remote_profile(
media_dir: &Path, media_dir: &Path,
profile: DbActorProfile, profile: DbActorProfile,
actor: Actor, actor: Actor,
) -> Result<DbActorProfile, ImportError> { ) -> Result<DbActorProfile, HandlerError> {
let actor_old = profile.actor_json.ok_or(ImportError::LocalObject)?; let actor_old = profile.actor_json.ok_or(HandlerError::LocalObject)?;
if actor_old.id != actor.id { if actor_old.id != actor.id {
log::warn!( log::warn!(
"actor ID changed from {} to {}", "actor ID changed from {} to {}",

View file

@ -4,13 +4,21 @@ use serde_json::Value;
use tokio_postgres::GenericClient; use tokio_postgres::GenericClient;
use crate::config::Config; use crate::config::Config;
use crate::errors::{ConversionError, ValidationError}; use crate::errors::{
ConversionError,
DatabaseError,
HttpError,
ValidationError,
};
use crate::http_signatures::verify::{ use crate::http_signatures::verify::{
verify_signed_request, verify_signed_request,
VerificationError, VerificationError,
}; };
use super::activity::{Activity, Object}; use super::activity::{Activity, Object};
use super::fetcher::helpers::{import_post, ImportError}; use super::fetcher::{
fetchers::FetchError,
helpers::import_post,
};
use super::handlers::{ use super::handlers::{
accept_follow::handle_accept_follow, accept_follow::handle_accept_follow,
add::handle_add, add::handle_add,
@ -28,6 +36,40 @@ use super::handlers::{
}; };
use super::vocabulary::*; use super::vocabulary::*;
#[derive(thiserror::Error, Debug)]
pub enum HandlerError {
#[error("local object")]
LocalObject,
#[error(transparent)]
FetchError(#[from] FetchError),
#[error(transparent)]
ValidationError(#[from] ValidationError),
#[error(transparent)]
DatabaseError(#[from] DatabaseError),
#[error(transparent)]
AuthError(#[from] VerificationError),
}
impl From<HandlerError> for HttpError {
fn from(error: HandlerError) -> Self {
match error {
HandlerError::LocalObject => HttpError::InternalError,
HandlerError::FetchError(error) => {
HttpError::ValidationError(error.to_string())
},
HandlerError::ValidationError(error) => error.into(),
HandlerError::DatabaseError(error) => error.into(),
HandlerError::AuthError(_) => {
HttpError::AuthError("invalid signature")
},
}
}
}
/// Transforms arbitrary property value into array of strings /// Transforms arbitrary property value into array of strings
pub fn parse_array(value: &Value) -> Result<Vec<String>, ConversionError> { pub fn parse_array(value: &Value) -> Result<Vec<String>, ConversionError> {
let result = match value { let result = match value {
@ -108,7 +150,7 @@ pub async fn receive_activity(
db_client: &mut impl GenericClient, db_client: &mut impl GenericClient,
request: &HttpRequest, request: &HttpRequest,
activity_raw: &Value, activity_raw: &Value,
) -> Result<(), ImportError> { ) -> Result<(), HandlerError> {
let activity: Activity = serde_json::from_value(activity_raw.clone()) let activity: Activity = serde_json::from_value(activity_raw.clone())
.map_err(|_| ValidationError("invalid activity"))?; .map_err(|_| ValidationError("invalid activity"))?;
let activity_type = activity.activity_type.clone(); let activity_type = activity.activity_type.clone();

View file

@ -9,9 +9,9 @@ use regex::Regex;
use rsa::RsaPublicKey; use rsa::RsaPublicKey;
use tokio_postgres::GenericClient; use tokio_postgres::GenericClient;
use crate::activitypub::fetcher::helpers::{ use crate::activitypub::{
get_or_import_profile_by_actor_id, fetcher::helpers::get_or_import_profile_by_actor_id,
ImportError, handlers::HandlerError,
}; };
use crate::config::Config; use crate::config::Config;
use crate::errors::DatabaseError; use crate::errors::DatabaseError;
@ -183,7 +183,7 @@ pub async fn verify_signed_request(
&actor_id, &actor_id,
).await { ).await {
Ok(profile) => profile, Ok(profile) => profile,
Err(ImportError::DatabaseError(error)) => return Err(error.into()), Err(HandlerError::DatabaseError(error)) => return Err(error.into()),
Err(other_error) => { Err(other_error) => {
return Err(VerificationError::ActorError(other_error.to_string())); return Err(VerificationError::ActorError(other_error.to_string()));
}, },