Process follower migration request in background
This commit is contained in:
parent
62069dc011
commit
e02ebebe02
2 changed files with 85 additions and 55 deletions
|
@ -3,6 +3,10 @@ use uuid::Uuid;
|
||||||
use mitra_config::Config;
|
use mitra_config::Config;
|
||||||
|
|
||||||
use crate::activitypub::{
|
use crate::activitypub::{
|
||||||
|
builders::{
|
||||||
|
move_person::prepare_move_person,
|
||||||
|
undo_follow::prepare_undo_follow,
|
||||||
|
},
|
||||||
fetcher::helpers::get_or_import_profile_by_actor_address,
|
fetcher::helpers::get_or_import_profile_by_actor_address,
|
||||||
HandlerError,
|
HandlerError,
|
||||||
};
|
};
|
||||||
|
@ -15,9 +19,15 @@ use crate::database::{
|
||||||
use crate::errors::ValidationError;
|
use crate::errors::ValidationError;
|
||||||
use crate::mastodon_api::accounts::helpers::follow_or_create_request;
|
use crate::mastodon_api::accounts::helpers::follow_or_create_request;
|
||||||
use crate::models::{
|
use crate::models::{
|
||||||
profiles::types::DbActorProfile,
|
|
||||||
posts::mentions::mention_to_address,
|
posts::mentions::mention_to_address,
|
||||||
relationships::queries::{get_followers, get_following},
|
profiles::queries::get_profile_by_acct,
|
||||||
|
profiles::types::DbActorProfile,
|
||||||
|
relationships::queries::{
|
||||||
|
follow,
|
||||||
|
get_followers,
|
||||||
|
get_following,
|
||||||
|
unfollow,
|
||||||
|
},
|
||||||
users::types::User,
|
users::types::User,
|
||||||
};
|
};
|
||||||
use crate::webfinger::types::ActorAddress;
|
use crate::webfinger::types::ActorAddress;
|
||||||
|
@ -108,6 +118,64 @@ pub async fn import_follows_task(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn move_followers_task(
|
||||||
|
config: &Config,
|
||||||
|
db_pool: &DbPool,
|
||||||
|
current_user: User,
|
||||||
|
from_actor_id: &str,
|
||||||
|
maybe_from_profile: Option<DbActorProfile>,
|
||||||
|
address_list: Vec<ActorAddress>,
|
||||||
|
) -> Result<(), anyhow::Error> {
|
||||||
|
let db_client = &mut **get_database_client(db_pool).await?;
|
||||||
|
let instance = config.instance();
|
||||||
|
let mut followers = vec![];
|
||||||
|
for follower_address in address_list {
|
||||||
|
let follower_acct = follower_address.acct(&instance.hostname());
|
||||||
|
// TODO: fetch unknown profiles
|
||||||
|
let follower = get_profile_by_acct(db_client, &follower_acct).await?;
|
||||||
|
if let Some(remote_actor) = follower.actor_json {
|
||||||
|
// Add remote actor to activity recipients list
|
||||||
|
followers.push(remote_actor);
|
||||||
|
} else {
|
||||||
|
// Immediately move local followers (only if alias can be verified)
|
||||||
|
if let Some(ref from_profile) = maybe_from_profile {
|
||||||
|
match unfollow(db_client, &follower.id, &from_profile.id).await {
|
||||||
|
Ok(maybe_follow_request_id) => {
|
||||||
|
// Send Undo(Follow) to a remote actor
|
||||||
|
let remote_actor = from_profile.actor_json.as_ref()
|
||||||
|
.expect("actor data must be present");
|
||||||
|
let follow_request_id = maybe_follow_request_id
|
||||||
|
.expect("follow request must exist");
|
||||||
|
prepare_undo_follow(
|
||||||
|
&instance,
|
||||||
|
¤t_user,
|
||||||
|
remote_actor,
|
||||||
|
&follow_request_id,
|
||||||
|
).enqueue(db_client).await?;
|
||||||
|
},
|
||||||
|
// Not a follower, ignore
|
||||||
|
Err(DatabaseError::NotFound(_)) => continue,
|
||||||
|
Err(other_error) => return Err(other_error.into()),
|
||||||
|
};
|
||||||
|
match follow(db_client, &follower.id, ¤t_user.id).await {
|
||||||
|
Ok(_) => (),
|
||||||
|
// Ignore if already following
|
||||||
|
Err(DatabaseError::AlreadyExists(_)) => (),
|
||||||
|
Err(other_error) => return Err(other_error.into()),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
prepare_move_person(
|
||||||
|
&instance,
|
||||||
|
¤t_user,
|
||||||
|
from_actor_id,
|
||||||
|
followers,
|
||||||
|
None,
|
||||||
|
).enqueue(db_client).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::activitypub::actors::types::Actor;
|
use crate::activitypub::actors::types::Actor;
|
||||||
|
|
|
@ -11,12 +11,6 @@ use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
use mitra_config::Config;
|
use mitra_config::Config;
|
||||||
use mitra_utils::passwords::hash_password;
|
use mitra_utils::passwords::hash_password;
|
||||||
|
|
||||||
use crate::activitypub::{
|
|
||||||
builders::{
|
|
||||||
move_person::prepare_move_person,
|
|
||||||
undo_follow::prepare_undo_follow,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
use crate::database::{get_database_client, DatabaseError, DbPool};
|
use crate::database::{get_database_client, DatabaseError, DbPool};
|
||||||
use crate::errors::ValidationError;
|
use crate::errors::ValidationError;
|
||||||
use crate::http::get_request_base_url;
|
use crate::http::get_request_base_url;
|
||||||
|
@ -27,14 +21,14 @@ use crate::mastodon_api::{
|
||||||
};
|
};
|
||||||
use crate::models::{
|
use crate::models::{
|
||||||
profiles::helpers::find_aliases,
|
profiles::helpers::find_aliases,
|
||||||
profiles::queries::{get_profile_by_acct, get_profile_by_remote_actor_id},
|
profiles::queries::get_profile_by_remote_actor_id,
|
||||||
relationships::queries::{follow, unfollow},
|
|
||||||
users::queries::set_user_password,
|
users::queries::set_user_password,
|
||||||
};
|
};
|
||||||
use super::helpers::{
|
use super::helpers::{
|
||||||
export_followers,
|
export_followers,
|
||||||
export_follows,
|
export_follows,
|
||||||
import_follows_task,
|
import_follows_task,
|
||||||
|
move_followers_task,
|
||||||
parse_address_list,
|
parse_address_list,
|
||||||
};
|
};
|
||||||
use super::types::{
|
use super::types::{
|
||||||
|
@ -158,52 +152,20 @@ async fn move_followers(
|
||||||
return Err(ValidationError("old profile is not an alias").into());
|
return Err(ValidationError("old profile is not an alias").into());
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
let mut followers = vec![];
|
|
||||||
let address_list = parse_address_list(&request_data.followers_csv)?;
|
let address_list = parse_address_list(&request_data.followers_csv)?;
|
||||||
for follower_address in address_list {
|
let current_user_clone = current_user.clone();
|
||||||
let follower_acct = follower_address.acct(&instance.hostname());
|
tokio::spawn(async move {
|
||||||
// TODO: fetch unknown profiles
|
move_followers_task(
|
||||||
let follower = get_profile_by_acct(db_client, &follower_acct).await?;
|
&config,
|
||||||
if let Some(remote_actor) = follower.actor_json {
|
&db_pool,
|
||||||
// Add remote actor to activity recipients list
|
current_user_clone,
|
||||||
followers.push(remote_actor);
|
&request_data.from_actor_id,
|
||||||
} else {
|
maybe_from_profile,
|
||||||
// Immediately move local followers (only if alias can be verified)
|
address_list,
|
||||||
if let Some(ref from_profile) = maybe_from_profile {
|
).await.unwrap_or_else(|error| {
|
||||||
match unfollow(db_client, &follower.id, &from_profile.id).await {
|
log::error!("move followers: {}", error);
|
||||||
Ok(maybe_follow_request_id) => {
|
});
|
||||||
// Send Undo(Follow) to a remote actor
|
});
|
||||||
let remote_actor = from_profile.actor_json.as_ref()
|
|
||||||
.expect("actor data must be present");
|
|
||||||
let follow_request_id = maybe_follow_request_id
|
|
||||||
.expect("follow request must exist");
|
|
||||||
prepare_undo_follow(
|
|
||||||
&instance,
|
|
||||||
¤t_user,
|
|
||||||
remote_actor,
|
|
||||||
&follow_request_id,
|
|
||||||
).enqueue(db_client).await?;
|
|
||||||
},
|
|
||||||
// Not a follower, ignore
|
|
||||||
Err(DatabaseError::NotFound(_)) => continue,
|
|
||||||
Err(other_error) => return Err(other_error.into()),
|
|
||||||
};
|
|
||||||
match follow(db_client, &follower.id, ¤t_user.id).await {
|
|
||||||
Ok(_) => (),
|
|
||||||
// Ignore if already following
|
|
||||||
Err(DatabaseError::AlreadyExists(_)) => (),
|
|
||||||
Err(other_error) => return Err(other_error.into()),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
prepare_move_person(
|
|
||||||
&instance,
|
|
||||||
¤t_user,
|
|
||||||
&request_data.from_actor_id,
|
|
||||||
followers,
|
|
||||||
None,
|
|
||||||
).enqueue(db_client).await?;
|
|
||||||
|
|
||||||
let account = Account::from_user(
|
let account = Account::from_user(
|
||||||
&get_request_base_url(connection_info),
|
&get_request_base_url(connection_info),
|
||||||
|
|
Loading…
Reference in a new issue