Add template
field to Link
because ostatus subscribe schema needs it.
#4
1 changed files with 136 additions and 8 deletions
|
@ -114,6 +114,7 @@ impl Resource {
|
|||
.map(clone_hashmap_with_option_value_as_complete)
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
template: Some(link.template.clone().unwrap_or_default()),
|
||||
}
|
||||
}))
|
||||
})
|
||||
|
@ -146,6 +147,36 @@ impl Resource {
|
|||
.links
|
||||
.filter(|links| !links.is_empty())
|
||||
.map(|mut links| {
|
||||
// Collapse default subvalues
|
||||
for link in &mut links {
|
||||
if link.media_type.as_ref().map_or(false, String::is_empty) {
|
||||
link.media_type = None;
|
||||
}
|
||||
if link.href.as_ref().map_or(false, String::is_empty) {
|
||||
link.href = None;
|
||||
}
|
||||
if let Some(titles) = &mut link.titles {
|
||||
titles.retain(|key, value| !key.is_empty() || !value.is_empty())
|
||||
}
|
||||
if link.titles.as_ref().map_or(false, HashMap::is_empty) {
|
||||
link.titles = None;
|
||||
}
|
||||
if let Some(properties) = &mut link.properties {
|
||||
for value in properties.values_mut() {
|
||||
if value.as_ref().map_or(false, String::is_empty) {
|
||||
*value = None;
|
||||
}
|
||||
}
|
||||
properties.retain(|key, value| !key.is_empty() || !value.is_none())
|
||||
}
|
||||
if link.properties.as_ref().map_or(false, HashMap::is_empty) {
|
||||
link.properties = None;
|
||||
}
|
||||
if link.template.as_ref().map_or(false, String::is_empty) {
|
||||
link.template = None;
|
||||
}
|
||||
}
|
||||
// Delete completely default links
|
||||
links.retain(|link| {
|
||||
// Empty `rel` is invalid, but short-circuiting here would delete records
|
||||
// that are only partially edited. Better to store invalid data than to delete
|
||||
|
@ -153,22 +184,19 @@ impl Resource {
|
|||
let mut is_default = link.rel.is_empty();
|
||||
is_default &= link
|
||||
.media_type
|
||||
.as_ref()
|
||||
.filter(|media_type| !media_type.is_empty())
|
||||
.is_none();
|
||||
is_default &= link.href.as_ref().filter(|href| !href.is_empty()).is_none();
|
||||
is_default &= link
|
||||
.titles
|
||||
.as_ref()
|
||||
.filter(|titles| !titles.is_empty())
|
||||
.is_none();
|
||||
is_default &= link
|
||||
.properties
|
||||
.as_ref()
|
||||
.filter(|titles| !titles.is_empty())
|
||||
.is_none();
|
||||
is_default &= link
|
||||
.template
|
||||
.is_none();
|
||||
|
||||
is_default
|
||||
!is_default
|
||||
});
|
||||
|
||||
links
|
||||
|
@ -189,12 +217,15 @@ pub struct Link {
|
|||
pub titles: Option<HashMap<String, String>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub properties: Option<HashMap<String, Option<String>>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub template: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// Functions to generate data for testing functions that manipulate `Resource` structs
|
||||
pub mod test_data {
|
||||
use crate::schema::resource::Resource;
|
||||
use std::collections::HashMap;
|
||||
use crate::schema::resource::{Link, Resource};
|
||||
|
||||
/// A [`Resource`] with only the `subject` field set
|
||||
pub fn barebones_user() -> Resource {
|
||||
|
@ -220,6 +251,100 @@ pub mod test_data {
|
|||
links: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn example_mastodon_user() -> Resource {
|
||||
Resource {
|
||||
subject: "acct:user@example.com".to_string(),
|
||||
aliases: Some(vec![
|
||||
"https://example.com/@user".to_string(),
|
||||
"https://example.com/users/user".to_string()
|
||||
]),
|
||||
properties: None,
|
||||
links: Some(vec![
|
||||
Link {
|
||||
rel: "http://webfinger.net/rel/profile-page".to_string(),
|
||||
media_type: Some("text/html".to_string()),
|
||||
href: Some("https://example.com/@user".to_string()),
|
||||
titles: None,
|
||||
properties: None,
|
||||
template: None,
|
||||
},
|
||||
Link {
|
||||
rel: "self".to_string(),
|
||||
media_type: Some("application/activity+json".to_string()),
|
||||
href: Some("https://example.com/users/user".to_string()),
|
||||
titles: None,
|
||||
properties: None,
|
||||
template: None,
|
||||
},
|
||||
Link {
|
||||
rel: "http://ostatus.org/schema/1.0/subscribe".to_string(),
|
||||
media_type: None,
|
||||
href: None,
|
||||
titles: None,
|
||||
properties: None,
|
||||
template: Some("https://example.com/authorize_interaction?uri={uri}".to_string()),
|
||||
},
|
||||
Link {
|
||||
rel: "http://webfinger.net/rel/avatar".to_string(),
|
||||
media_type: Some("image/png".to_string()),
|
||||
href: Some("https://example.com/system/accounts/avatars/321/423/112/234/123/527/original/1j2ioff88a9wa.png".to_string()),
|
||||
titles: None,
|
||||
properties: None,
|
||||
template: None,
|
||||
}
|
||||
]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn example_firefish_user() -> Resource {
|
||||
Resource {
|
||||
subject: "acct:user@example.com".to_string(),
|
||||
aliases: None,
|
||||
properties: None,
|
||||
links: Some(vec![
|
||||
Link {
|
||||
rel: "self".to_string(),
|
||||
media_type: Some("application/activity+json".to_string()),
|
||||
href: Some("https://example.com/users/8fsua89lcieaj".to_string()),
|
||||
titles: None,
|
||||
properties: None,
|
||||
template: None,
|
||||
},
|
||||
Link {
|
||||
rel: "http://webfinger.net/rel/profile-page".to_string(),
|
||||
media_type: Some("text/html".to_string()),
|
||||
href: Some("https://example.com/@user".to_string()),
|
||||
titles: None,
|
||||
properties: None,
|
||||
template: None,
|
||||
},
|
||||
Link {
|
||||
rel: "http://ostatus.org/schema/1.0/subscribe".to_string(),
|
||||
media_type: None,
|
||||
href: None,
|
||||
titles: None,
|
||||
properties: None,
|
||||
template: Some("https://example.com/authorize-follow?acct={uri}".to_string()),
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
pub fn full_resource() -> Resource {
|
||||
Resource {
|
||||
subject: "some_subject".to_string(),
|
||||
aliases: Some(vec!["ThisIsAnAlias".to_string()]),
|
||||
properties: Some(HashMap::from_iter(std::iter::once(("property_key".to_string(), Some("property_value".to_string()))))),
|
||||
links: Some(vec![Link {
|
||||
rel: "link_relation".to_string(),
|
||||
media_type: Some("media/type".to_string()),
|
||||
href: Some("https://example.com/link_href".to_string()),
|
||||
titles: Some(HashMap::from_iter(std::iter::once(("title_key".to_string(), "title_value".to_string())))),
|
||||
properties: Some(HashMap::from_iter(std::iter::once(("property_key".to_string(), Some("property_value".to_string()))))),
|
||||
template: Some("template".to_string()),
|
||||
}]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -288,6 +413,9 @@ mod tests {
|
|||
test_data::barebones_user(),
|
||||
test_data::user_with_matching_subject_and_alias(),
|
||||
test_data::user_with_single_alias(),
|
||||
test_data::example_firefish_user(),
|
||||
test_data::example_mastodon_user(),
|
||||
test_data::full_resource(),
|
||||
] {
|
||||
assert_eq!(data, data.as_completely_serializable().compress());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue