Prevent profile import error in case of webfinger redirection

This commit is contained in:
silverpill 2021-12-22 23:27:32 +00:00
parent c13b110ca2
commit 2703ab717a
2 changed files with 47 additions and 21 deletions

View file

@ -39,7 +39,7 @@ use crate::models::relationships::queries::{
}; };
use crate::models::users::queries::get_user_by_id; use crate::models::users::queries::get_user_by_id;
use super::activity::{Object, Activity, create_activity_accept_follow}; use super::activity::{Object, Activity, create_activity_accept_follow};
use super::actor::Actor; use super::actor::{Actor, ActorAddress};
use super::deliverer::deliver_activity; use super::deliverer::deliver_activity;
use super::fetcher::{ use super::fetcher::{
fetch_avatar_and_banner, fetch_avatar_and_banner,
@ -131,6 +131,7 @@ async fn get_or_fetch_profile_by_actor_id(
log::warn!("{}", err); log::warn!("{}", err);
ValidationError("failed to fetch actor") ValidationError("failed to fetch actor")
})?; })?;
log::info!("fetched profile {}", profile_data.acct);
let profile = create_profile(db_client, &profile_data).await?; let profile = create_profile(db_client, &profile_data).await?;
profile profile
}, },
@ -139,6 +140,32 @@ async fn get_or_fetch_profile_by_actor_id(
Ok(profile) Ok(profile)
} }
/// Fetches actor profile and saves it into database
pub async fn import_profile_by_actor_address(
db_client: &impl GenericClient,
instance: &Instance,
media_dir: &Path,
actor_address: &ActorAddress,
) -> Result<DbActorProfile, HttpError> {
let profile_data = fetch_profile(
instance,
&actor_address.username,
&actor_address.instance,
media_dir,
).await.map_err(|_| ValidationError("failed to fetch actor"))?;
if profile_data.acct != actor_address.acct() {
// Redirected to different server
match get_profile_by_acct(db_client, &profile_data.acct).await {
Ok(profile) => return Ok(profile),
Err(DatabaseError::NotFound(_)) => (),
Err(other_error) => return Err(other_error.into()),
};
};
log::info!("fetched profile {}", profile_data.acct);
let profile = create_profile(db_client, &profile_data).await?;
Ok(profile)
}
pub async fn process_note( pub async fn process_note(
config: &Config, config: &Config,
db_client: &mut impl GenericClient, db_client: &mut impl GenericClient,
@ -264,14 +291,12 @@ pub async fn process_note(
).await { ).await {
Ok(profile) => profile, Ok(profile) => profile,
Err(DatabaseError::NotFound(_)) => { Err(DatabaseError::NotFound(_)) => {
let profile_data = fetch_profile( import_profile_by_actor_address(
db_client,
&config.instance(), &config.instance(),
&actor_address.username,
&actor_address.instance,
&config.media_dir(), &config.media_dir(),
).await.map_err(|_| ValidationError("failed to fetch actor"))?; &actor_address,
let profile = create_profile(db_client, &profile_data).await?; ).await?
profile
}, },
Err(other_error) => return Err(other_error.into()), Err(other_error) => return Err(other_error.into()),
}; };

View file

@ -1,14 +1,17 @@
use regex::Regex; use regex::Regex;
use tokio_postgres::GenericClient; use tokio_postgres::GenericClient;
use crate::activitypub::fetcher::fetch_profile; use crate::activitypub::actor::ActorAddress;
use crate::activitypub::receiver::process_note; use crate::activitypub::receiver::{
import_profile_by_actor_address,
process_note,
};
use crate::config::Config; use crate::config::Config;
use crate::errors::{ValidationError, HttpError}; use crate::errors::{ValidationError, HttpError};
use crate::mastodon_api::accounts::types::Account; use crate::mastodon_api::accounts::types::Account;
use crate::mastodon_api::statuses::types::Status; use crate::mastodon_api::statuses::types::Status;
use crate::models::posts::types::Post; use crate::models::posts::types::Post;
use crate::models::profiles::queries::{create_profile, search_profile}; use crate::models::profiles::queries::search_profile;
use crate::models::profiles::types::DbActorProfile; use crate::models::profiles::types::DbActorProfile;
use super::types::SearchResults; use super::types::SearchResults;
@ -48,20 +51,18 @@ async fn search_profiles(
}; };
let mut profiles = search_profile(db_client, &username, instance.as_ref()).await?; let mut profiles = search_profile(db_client, &username, instance.as_ref()).await?;
if profiles.is_empty() && instance.is_some() { if profiles.is_empty() && instance.is_some() {
let actor_host = instance.unwrap(); let actor_address = ActorAddress {
// TODO: return error when trying to fetch local profile username: username,
match fetch_profile( instance: instance.unwrap(),
is_local: false,
};
match import_profile_by_actor_address(
db_client,
&config.instance(), &config.instance(),
&username,
&actor_host,
&config.media_dir(), &config.media_dir(),
&actor_address,
).await { ).await {
Ok(profile_data) => { Ok(profile) => {
let profile = create_profile(db_client, &profile_data).await?;
log::info!(
"imported profile '{}'",
profile.acct,
);
profiles.push(profile); profiles.push(profile);
}, },
Err(err) => { Err(err) => {