Validate and clean extra fields when importing profile

This commit is contained in:
silverpill 2022-02-17 21:08:43 +00:00
parent 0993a3b38c
commit 50630c004a
2 changed files with 41 additions and 20 deletions

View file

@ -11,11 +11,11 @@ use uuid::Uuid;
use crate::activitypub::actor::Actor; use crate::activitypub::actor::Actor;
use crate::activitypub::views::get_actor_url; use crate::activitypub::views::get_actor_url;
use crate::errors::ValidationError; use crate::errors::ValidationError;
use crate::utils::html::clean_html_strict;
use super::validators::{ use super::validators::{
validate_username, validate_username,
validate_display_name, validate_display_name,
clean_bio, clean_bio,
clean_extra_fields,
}; };
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
@ -163,6 +163,7 @@ impl ProfileCreateData {
let cleaned_bio = clean_bio(bio, self.actor_json.is_some())?; let cleaned_bio = clean_bio(bio, self.actor_json.is_some())?;
self.bio = Some(cleaned_bio); self.bio = Some(cleaned_bio);
}; };
self.extra_fields = clean_extra_fields(&self.extra_fields)?;
Ok(()) Ok(())
} }
} }
@ -188,25 +189,7 @@ impl ProfileUpdateData {
self.bio = Some(cleaned_bio); self.bio = Some(cleaned_bio);
}; };
// Clean extra fields and remove fields with empty labels // Clean extra fields and remove fields with empty labels
self.extra_fields = self.extra_fields.iter().cloned() self.extra_fields = clean_extra_fields(&self.extra_fields)?;
.map(|mut field| {
field.name = field.name.trim().to_string();
field.value = clean_html_strict(&field.value);
field
})
.filter(|field| !field.name.is_empty())
.collect();
// Validate extra fields
if self.extra_fields.len() >= 10 {
return Err(ValidationError("at most 10 fields are allowed"));
}
let mut unique_labels: Vec<String> = self.extra_fields.iter()
.map(|field| field.name.clone()).collect();
unique_labels.sort();
unique_labels.dedup();
if unique_labels.len() < self.extra_fields.len() {
return Err(ValidationError("duplicate labels"));
};
Ok(()) Ok(())
} }
} }

View file

@ -1,6 +1,7 @@
use regex::Regex; use regex::Regex;
use crate::errors::ValidationError; use crate::errors::ValidationError;
use crate::utils::html::{clean_html, clean_html_strict}; use crate::utils::html::{clean_html, clean_html_strict};
use super::types::ExtraField;
const USERNAME_RE: &str = r"^[a-zA-Z0-9_\.-]+$"; const USERNAME_RE: &str = r"^[a-zA-Z0-9_\.-]+$";
@ -43,6 +44,31 @@ pub fn clean_bio(bio: &str, is_remote: bool) -> Result<String, ValidationError>
Ok(cleaned_bio) Ok(cleaned_bio)
} }
/// Validates extra fields and removes fields with empty labels
pub fn clean_extra_fields(extra_fields: &[ExtraField])
-> Result<Vec<ExtraField>, ValidationError>
{
let cleaned_extra_fields: Vec<_> = extra_fields.iter().cloned()
.map(|mut field| {
field.name = field.name.trim().to_string();
field.value = clean_html_strict(&field.value);
field
})
.filter(|field| !field.name.is_empty())
.collect();
if cleaned_extra_fields.len() >= 10 {
return Err(ValidationError("at most 10 fields are allowed"));
};
let mut unique_labels: Vec<String> = cleaned_extra_fields.iter()
.map(|field| field.name.clone()).collect();
unique_labels.sort();
unique_labels.dedup();
if unique_labels.len() < cleaned_extra_fields.len() {
return Err(ValidationError("duplicate labels"));
};
Ok(cleaned_extra_fields)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -80,4 +106,16 @@ mod tests {
let result = clean_bio(bio, true).unwrap(); let result = clean_bio(bio, true).unwrap();
assert_eq!(result, "test\n123"); assert_eq!(result, "test\n123");
} }
#[test]
fn test_clean_extra_fields() {
let extra_fields = vec![ExtraField {
name: " $ETH ".to_string(),
value: "<p>0x1234</p>".to_string(),
value_source: None,
}];
let result = clean_extra_fields(&extra_fields).unwrap().pop().unwrap();
assert_eq!(result.name, "$ETH");
assert_eq!(result.value, "0x1234");
}
} }