From 82e24ad8b0cc9360d8f15d51b6501bad149cd14c Mon Sep 17 00:00:00 2001 From: silverpill Date: Thu, 17 Feb 2022 00:03:27 +0000 Subject: [PATCH] Validate and clean bio when profile is created or updated --- src/activitypub/fetcher/helpers.rs | 4 +-- src/models/profiles/types.rs | 19 +++++++++++--- src/models/profiles/validators.rs | 41 +++++++++++++++++++++--------- 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/src/activitypub/fetcher/helpers.rs b/src/activitypub/fetcher/helpers.rs index b00f423..6cec1d6 100644 --- a/src/activitypub/fetcher/helpers.rs +++ b/src/activitypub/fetcher/helpers.rs @@ -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, diff --git a/src/models/profiles/types.rs b/src/models/profiles/types.rs index 5bbbfba..7f51f63 100644 --- a/src/models/profiles/types.rs +++ b/src/models/profiles/types.rs @@ -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| { diff --git a/src/models/profiles/validators.rs b/src/models/profiles/validators.rs index 6580c0f..772fa0e 100644 --- a/src/models/profiles/validators.rs +++ b/src/models/profiles/validators.rs @@ -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")); - }; + 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 { + 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\n123"; + let result = clean_bio(bio, true).unwrap(); + assert_eq!(result, "test\n123"); } }