Validate and clean bio when profile is created or updated

This commit is contained in:
silverpill 2022-02-17 00:03:27 +00:00
parent 4e010f1698
commit 82e24ad8b0
3 changed files with 47 additions and 17 deletions

View file

@ -57,7 +57,7 @@ pub async fn get_or_import_profile_by_actor_id(
let profile = match get_profile_by_actor_id(db_client, actor_id).await {
Ok(profile) => profile,
Err(DatabaseError::NotFound(_)) => {
let profile_data = fetch_profile_by_actor_id(
let mut profile_data = fetch_profile_by_actor_id(
instance, actor_id, media_dir,
)
.await
@ -85,7 +85,7 @@ pub async fn import_profile_by_actor_address(
if actor_address.instance == instance.host() {
return Err(ImportError::LocalObject);
};
let profile_data = fetch_profile(
let mut profile_data = fetch_profile(
instance,
&actor_address.username,
&actor_address.instance,

View file

@ -15,6 +15,7 @@ use crate::utils::html::clean_html_strict;
use super::validators::{
validate_username,
validate_display_name,
clean_bio,
};
#[derive(Clone, Debug, Deserialize, Serialize)]
@ -153,9 +154,15 @@ pub struct ProfileCreateData {
}
impl ProfileCreateData {
pub fn clean(&self) -> Result<(), ValidationError> {
pub fn clean(&mut self) -> Result<(), ValidationError> {
validate_username(&self.username)?;
validate_display_name(self.display_name.as_ref())?;
if let Some(display_name) = &self.display_name {
validate_display_name(display_name)?;
};
if let Some(bio) = &self.bio {
let cleaned_bio = clean_bio(bio, self.actor_json.is_some())?;
self.bio = Some(cleaned_bio);
};
Ok(())
}
}
@ -172,8 +179,14 @@ pub struct ProfileUpdateData {
impl ProfileUpdateData {
pub fn clean(&mut self) -> Result<(), ValidationError> {
if let Some(display_name) = &self.display_name {
validate_display_name(display_name)?;
};
// Validate and clean bio
self.bio = self.bio.as_ref().map(|val| clean_html_strict(val));
if let Some(bio) = &self.bio {
let cleaned_bio = clean_bio(bio, self.actor_json.is_some())?;
self.bio = Some(cleaned_bio);
};
// Clean extra fields and remove fields with empty labels
self.extra_fields = self.extra_fields.iter().cloned()
.map(|mut field| {

View file

@ -1,4 +1,5 @@
use crate::errors::ValidationError;
use crate::utils::html::{clean_html, clean_html_strict};
pub fn validate_username(username: &str) -> Result<(), ValidationError> {
if username.len() > 100 {
@ -7,17 +8,31 @@ pub fn validate_username(username: &str) -> Result<(), ValidationError> {
Ok(())
}
pub fn validate_display_name(display_name: Option<&String>)
pub fn validate_display_name(display_name: &str)
-> Result<(), ValidationError>
{
if let Some(display_name) = display_name {
if display_name.len() > 200 {
return Err(ValidationError("display name is too long"));
};
};
Ok(())
}
const BIO_MAX_SIZE: usize = 10000;
pub fn clean_bio(bio: &str, is_remote: bool) -> Result<String, ValidationError> {
if bio.len() > BIO_MAX_SIZE {
return Err(ValidationError("bio is too long"));
};
let cleaned_bio = if is_remote {
// Remote profile
clean_html(bio)
} else {
// Local profile
clean_html_strict(bio)
};
Ok(cleaned_bio)
}
#[cfg(test)]
mod tests {
use super::*;
@ -32,15 +47,17 @@ mod tests {
#[test]
fn test_validate_display_name() {
let display_name = "test".to_string();
let result_1 = validate_display_name(Some(&display_name));
let result_1 = validate_display_name("test");
assert!(result_1.is_ok());
let result_2 = validate_display_name(None);
assert!(result_2.is_ok());
let result_2 = validate_display_name(&"x".repeat(201));
assert!(result_2.is_err());
}
let display_name = "x".repeat(201);
let result_3 = validate_display_name(Some(&display_name));
assert!(result_3.is_err());
#[test]
fn test_clean_bio() {
let bio = "test\n<script>alert()</script>123";
let result = clean_bio(bio, true).unwrap();
assert_eq!(result, "test\n123");
}
}