Separate object URL handling from content validation

This commit is contained in:
silverpill 2023-01-31 18:03:24 +00:00
parent bc19a524c4
commit 01c894da9d
2 changed files with 37 additions and 30 deletions

View file

@ -19,7 +19,7 @@ use crate::activitypub::{
};
use crate::config::Config;
use crate::database::{DatabaseClient, DatabaseError};
use crate::errors::{ConversionError, ValidationError};
use crate::errors::ValidationError;
use crate::models::{
attachments::queries::create_attachment,
emojis::queries::{
@ -68,23 +68,22 @@ fn get_object_attributed_to(object: &Object)
Ok(author_id)
}
fn parse_object_url(value: &JsonValue) -> Result<String, ConversionError> {
let object_url = match value {
JsonValue::String(string) => string.to_owned(),
other_value => {
let links: Vec<Link> = parse_property_value(other_value)?;
if let Some(link) = links.get(0) {
link.href.clone()
} else {
return Err(ConversionError);
}
pub fn get_object_url(object: &Object) -> Result<String, ValidationError> {
let maybe_object_url = match &object.url {
Some(JsonValue::String(string)) => Some(string.to_owned()),
Some(other_value) => {
let links: Vec<Link> = parse_property_value(other_value)
.map_err(|_| ValidationError("invalid object URL"))?;
links.get(0).map(|link| link.href.clone())
},
None => None,
};
let object_url = maybe_object_url.unwrap_or(object.id.clone());
Ok(object_url)
}
pub fn get_object_content(object: &Object) -> Result<String, ValidationError> {
let mut content = if let Some(ref content) = object.content {
let content = if let Some(ref content) = object.content {
if object.media_type == Some("text/markdown".to_string()) {
format!("<p>{}</p>", content)
} else {
@ -95,19 +94,6 @@ pub fn get_object_content(object: &Object) -> Result<String, ValidationError> {
// Lemmy pages and PeerTube videos have "name" property
object.name.as_deref().unwrap_or("").to_string()
};
if object.object_type != NOTE {
// Append link to object
let object_url = if let Some(ref value) = object.url {
parse_object_url(value)
.map_err(|_| ValidationError("invalid object URL"))?
} else {
object.id.clone()
};
content += &format!(
r#"<p><a href="{0}">{0}</a></p>"#,
object_url,
);
};
if content.len() > CONTENT_MAX_SIZE {
return Err(ValidationError("content is too long"));
};
@ -115,6 +101,13 @@ pub fn get_object_content(object: &Object) -> Result<String, ValidationError> {
Ok(content_safe)
}
pub fn create_content_link(url: String) -> String {
format!(
r#"<p><a href="{0}" rel="noopener">{0}</a></p>"#,
url,
)
}
const ATTACHMENT_MAX_SIZE: usize = 20 * 1000 * 1000; // 20 MB
fn is_gnu_social_link(author_id: &str, attachment: &Attachment) -> bool {
@ -498,9 +491,13 @@ pub async fn handle_note(
log::warn!("failed to import {} ({})", author_id, err);
err
})?;
let content = get_object_content(&object)?;
let created_at = object.published.unwrap_or(Utc::now());
let mut content = get_object_content(&object)?;
if object.object_type != NOTE {
// Append link to object
let object_url = get_object_url(&object)?;
content += &create_content_link(object_url);
};
let attachments = get_object_attachments(
config,
db_client,
@ -556,6 +553,7 @@ pub async fn handle_note(
author.username,
);
};
let created_at = object.published.unwrap_or(Utc::now());
let post_data = PostCreateData {
content: content,
in_reply_to_id,
@ -638,7 +636,9 @@ mod tests {
}])),
..Default::default()
};
let content = get_object_content(&object).unwrap();
let mut content = get_object_content(&object).unwrap();
let object_url = get_object_url(&object).unwrap();
content += &create_content_link(object_url);
assert_eq!(
content,
r#"test-content<p><a href="https://example.org/xyz" rel="noopener">https://example.org/xyz</a></p>"#,

View file

@ -10,9 +10,11 @@ use crate::activitypub::{
types::Actor,
},
handlers::create::{
create_content_link,
get_object_attachments,
get_object_content,
get_object_tags,
get_object_url,
},
types::Object,
vocabulary::{NOTE, PERSON},
@ -46,8 +48,12 @@ async fn handle_update_note(
Err(DatabaseError::NotFound(_)) => return Ok(None),
Err(other_error) => return Err(other_error.into()),
};
let content = get_object_content(&object)?;
let updated_at = object.updated.unwrap_or(Utc::now());
let mut content = get_object_content(&object)?;
if object.object_type != NOTE {
// Append link to object
let object_url = get_object_url(&object)?;
content += &create_content_link(object_url);
};
let attachments = get_object_attachments(
config,
db_client,
@ -63,6 +69,7 @@ async fn handle_update_note(
&object,
&HashMap::new(),
).await?;
let updated_at = object.updated.unwrap_or(Utc::now());
let post_data = PostUpdateData {
content,
attachments,