Validate uploaded follower lists
This commit is contained in:
parent
1511b5f22b
commit
4c97246e3f
3 changed files with 50 additions and 9 deletions
|
@ -2,8 +2,13 @@ use tokio_postgres::GenericClient;
|
|||
use uuid::Uuid;
|
||||
|
||||
use crate::database::DatabaseError;
|
||||
use crate::models::profiles::types::DbActorProfile;
|
||||
use crate::models::relationships::queries::{get_followers, get_following};
|
||||
use crate::errors::ValidationError;
|
||||
use crate::models::{
|
||||
profiles::types::DbActorProfile,
|
||||
posts::mentions::mention_to_address,
|
||||
relationships::queries::{get_followers, get_following},
|
||||
};
|
||||
use crate::webfinger::types::ActorAddress;
|
||||
|
||||
fn export_profiles_to_csv(
|
||||
local_hostname: &str,
|
||||
|
@ -37,6 +42,22 @@ pub async fn export_follows(
|
|||
Ok(csv)
|
||||
}
|
||||
|
||||
pub fn parse_address_list(csv: &str)
|
||||
-> Result<Vec<ActorAddress>, ValidationError>
|
||||
{
|
||||
let mut addresses: Vec<_> = csv.lines()
|
||||
.map(|line| line.trim().to_string())
|
||||
.filter(|line| !line.is_empty())
|
||||
.map(|line| mention_to_address(&line))
|
||||
.collect::<Result<_, _>>()?;
|
||||
addresses.sort();
|
||||
addresses.dedup();
|
||||
if addresses.len() > 50 {
|
||||
return Err(ValidationError("can't process more than 50 items at once"));
|
||||
};
|
||||
Ok(addresses)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::activitypub::actors::types::Actor;
|
||||
|
@ -60,4 +81,22 @@ mod tests {
|
|||
);
|
||||
assert_eq!(csv, "user1@example.org\nuser2@test.net\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_address_list() {
|
||||
let csv = concat!(
|
||||
"\nuser1@example.net\n",
|
||||
"user2@example.com \n",
|
||||
"@user1@example.net",
|
||||
);
|
||||
let addresses = parse_address_list(csv).unwrap();
|
||||
assert_eq!(addresses.len(), 2);
|
||||
let addresses: Vec<_> = addresses.into_iter()
|
||||
.map(|address| address.to_string())
|
||||
.collect();
|
||||
assert_eq!(addresses, vec![
|
||||
"user1@example.net",
|
||||
"user2@example.com",
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use actix_web::{get, post, web, HttpResponse, Scope};
|
||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||
|
||||
|
@ -23,8 +21,11 @@ use crate::models::{
|
|||
users::queries::set_user_password,
|
||||
};
|
||||
use crate::utils::passwords::hash_password;
|
||||
use crate::webfinger::types::ActorAddress;
|
||||
use super::helpers::{export_followers, export_follows};
|
||||
use super::helpers::{
|
||||
export_followers,
|
||||
export_follows,
|
||||
parse_address_list,
|
||||
};
|
||||
use super::types::{MoveFollowersRequest, PasswordChangeRequest};
|
||||
|
||||
#[post("/change_password")]
|
||||
|
@ -114,9 +115,9 @@ async fn move_followers(
|
|||
};
|
||||
};
|
||||
let mut followers = vec![];
|
||||
for follower_address in request_data.followers_csv.lines() {
|
||||
let follower_acct = ActorAddress::from_str(follower_address)?
|
||||
.acct(&instance.hostname());
|
||||
let address_list = parse_address_list(&request_data.followers_csv)?;
|
||||
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 {
|
||||
|
|
|
@ -17,6 +17,7 @@ pub struct WebfingerQueryParams {
|
|||
pub resource: String,
|
||||
}
|
||||
|
||||
#[derive(Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub struct ActorAddress {
|
||||
pub username: String,
|
||||
pub hostname: String,
|
||||
|
|
Loading…
Reference in a new issue