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 crate::activitypub::activity::Object;
use crate::activitypub::actors::types::{Actor, ActorAddress};
use crate::activitypub::handlers::{
create_note::handle_note,
update_person::update_remote_profile,
use crate::activitypub::{
activity::Object,
actors::types::{Actor, ActorAddress},
handlers::{
create_note::handle_note,
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::errors::{DatabaseError, HttpError, ValidationError};
use crate::http_signatures::verify::VerificationError;
use crate::errors::{DatabaseError, ValidationError};
use crate::models::posts::queries::{
get_post_by_id,
get_post_by_remote_object_id,
@ -29,52 +31,17 @@ use super::fetchers::{
fetch_actor_images,
fetch_object,
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(
db_client: &impl GenericClient,
instance: &Instance,
media_dir: &Path,
actor: Actor,
) -> Result<DbActorProfile, ImportError> {
) -> Result<DbActorProfile, HandlerError> {
let actor_address = actor.address()?;
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()
.and_then(|aliases| aliases.first());
@ -112,9 +79,9 @@ pub async fn get_or_import_profile_by_actor_id(
instance: &Instance,
media_dir: &Path,
actor_id: &str,
) -> Result<DbActorProfile, ImportError> {
) -> Result<DbActorProfile, HandlerError> {
if actor_id.starts_with(&instance.url()) {
return Err(ImportError::LocalObject);
return Err(HandlerError::LocalObject);
};
let profile = match get_profile_by_remote_actor_id(
db_client,
@ -188,9 +155,9 @@ pub async fn import_profile_by_actor_address(
instance: &Instance,
media_dir: &Path,
actor_address: &ActorAddress,
) -> Result<DbActorProfile, ImportError> {
) -> Result<DbActorProfile, HandlerError> {
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 = fetch_actor(instance, &actor_id).await?;
@ -218,11 +185,11 @@ pub async fn import_post(
db_client: &mut impl GenericClient,
object_id: String,
object_received: Option<Object>,
) -> Result<Post, ImportError> {
) -> Result<Post, HandlerError> {
let instance = config.instance();
let media_dir = config.media_dir();
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

View file

@ -2,7 +2,6 @@ use tokio_postgres::GenericClient;
use crate::activitypub::{
activity::Activity,
fetcher::helpers::ImportError,
identifiers::parse_local_actor_id,
receiver::find_object_id,
vocabulary::PERSON,
@ -12,7 +11,7 @@ use crate::errors::ValidationError;
use crate::models::profiles::queries::get_profile_by_remote_actor_id;
use crate::models::relationships::queries::subscribe_opt;
use crate::models::users::queries::get_user_by_name;
use super::HandlerResult;
use super::{HandlerError, HandlerResult};
pub async fn handle_add(
config: &Config,
@ -23,7 +22,7 @@ pub async fn handle_add(
db_client,
&activity.actor,
).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_id = find_object_id(&target_value)?;
if Some(target_id) == actor.subscribers {

View file

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

View file

@ -3,7 +3,7 @@ use tokio_postgres::GenericClient;
use crate::activitypub::{
activity::Activity,
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,
receiver::find_object_id,
vocabulary::PERSON,
@ -12,7 +12,7 @@ use crate::config::Config;
use crate::errors::DatabaseError;
use crate::models::relationships::queries::follow;
use crate::models::users::queries::get_user_by_name;
use super::HandlerResult;
use super::{HandlerError, HandlerResult};
pub async fn handle_follow(
config: &Config,
@ -26,7 +26,7 @@ pub async fn handle_follow(
&activity.actor,
).await?;
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_username = parse_local_actor_id(
&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
// 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 add;

View file

@ -2,7 +2,6 @@ use tokio_postgres::GenericClient;
use crate::activitypub::{
activity::Activity,
fetcher::helpers::ImportError,
identifiers::parse_local_actor_id,
receiver::find_object_id,
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::relationships::queries::unsubscribe;
use crate::models::users::queries::get_user_by_name;
use super::HandlerResult;
use super::{HandlerError, HandlerResult};
pub async fn handle_remove(
config: &Config,
@ -26,7 +25,7 @@ pub async fn handle_remove(
db_client,
&activity.actor,
).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_id = find_object_id(&target_value)?;
if Some(target_id) == actor.subscribers {

View file

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

View file

@ -4,13 +4,21 @@ use serde_json::Value;
use tokio_postgres::GenericClient;
use crate::config::Config;
use crate::errors::{ConversionError, ValidationError};
use crate::errors::{
ConversionError,
DatabaseError,
HttpError,
ValidationError,
};
use crate::http_signatures::verify::{
verify_signed_request,
VerificationError,
};
use super::activity::{Activity, Object};
use super::fetcher::helpers::{import_post, ImportError};
use super::fetcher::{
fetchers::FetchError,
helpers::import_post,
};
use super::handlers::{
accept_follow::handle_accept_follow,
add::handle_add,
@ -28,6 +36,40 @@ use super::handlers::{
};
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
pub fn parse_array(value: &Value) -> Result<Vec<String>, ConversionError> {
let result = match value {
@ -108,7 +150,7 @@ pub async fn receive_activity(
db_client: &mut impl GenericClient,
request: &HttpRequest,
activity_raw: &Value,
) -> Result<(), ImportError> {
) -> Result<(), HandlerError> {
let activity: Activity = serde_json::from_value(activity_raw.clone())
.map_err(|_| ValidationError("invalid activity"))?;
let activity_type = activity.activity_type.clone();

View file

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