Add template
field to Link because ostatus subscribe schema needs it.
All checks were successful
/ cargo test (push) Successful in 20s
All checks were successful
/ cargo test (push) Successful in 20s
Also fixes a bug where Resource::compress lost every link and adds a lot more tests around that functionality.
This commit is contained in:
parent
8eafcf86b9
commit
efc7b83930
1 changed files with 136 additions and 8 deletions
|
@ -114,6 +114,7 @@ impl Resource {
|
||||||
.map(clone_hashmap_with_option_value_as_complete)
|
.map(clone_hashmap_with_option_value_as_complete)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
),
|
),
|
||||||
|
template: Some(link.template.clone().unwrap_or_default()),
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
@ -146,6 +147,36 @@ impl Resource {
|
||||||
.links
|
.links
|
||||||
.filter(|links| !links.is_empty())
|
.filter(|links| !links.is_empty())
|
||||||
.map(|mut links| {
|
.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| {
|
links.retain(|link| {
|
||||||
// Empty `rel` is invalid, but short-circuiting here would delete records
|
// Empty `rel` is invalid, but short-circuiting here would delete records
|
||||||
// that are only partially edited. Better to store invalid data than to delete
|
// 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();
|
let mut is_default = link.rel.is_empty();
|
||||||
is_default &= link
|
is_default &= link
|
||||||
.media_type
|
.media_type
|
||||||
.as_ref()
|
|
||||||
.filter(|media_type| !media_type.is_empty())
|
|
||||||
.is_none();
|
.is_none();
|
||||||
is_default &= link.href.as_ref().filter(|href| !href.is_empty()).is_none();
|
is_default &= link.href.as_ref().filter(|href| !href.is_empty()).is_none();
|
||||||
is_default &= link
|
is_default &= link
|
||||||
.titles
|
.titles
|
||||||
.as_ref()
|
|
||||||
.filter(|titles| !titles.is_empty())
|
|
||||||
.is_none();
|
.is_none();
|
||||||
is_default &= link
|
is_default &= link
|
||||||
.properties
|
.properties
|
||||||
.as_ref()
|
.is_none();
|
||||||
.filter(|titles| !titles.is_empty())
|
is_default &= link
|
||||||
|
.template
|
||||||
.is_none();
|
.is_none();
|
||||||
|
|
||||||
is_default
|
!is_default
|
||||||
});
|
});
|
||||||
|
|
||||||
links
|
links
|
||||||
|
@ -189,12 +217,15 @@ pub struct Link {
|
||||||
pub titles: Option<HashMap<String, String>>,
|
pub titles: Option<HashMap<String, String>>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub properties: Option<HashMap<String, Option<String>>>,
|
pub properties: Option<HashMap<String, Option<String>>>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub template: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
/// Functions to generate data for testing functions that manipulate `Resource` structs
|
/// Functions to generate data for testing functions that manipulate `Resource` structs
|
||||||
pub mod test_data {
|
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
|
/// A [`Resource`] with only the `subject` field set
|
||||||
pub fn barebones_user() -> Resource {
|
pub fn barebones_user() -> Resource {
|
||||||
|
@ -220,6 +251,100 @@ pub mod test_data {
|
||||||
links: None,
|
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)]
|
#[cfg(test)]
|
||||||
|
@ -288,6 +413,9 @@ mod tests {
|
||||||
test_data::barebones_user(),
|
test_data::barebones_user(),
|
||||||
test_data::user_with_matching_subject_and_alias(),
|
test_data::user_with_matching_subject_and_alias(),
|
||||||
test_data::user_with_single_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());
|
assert_eq!(data, data.as_completely_serializable().compress());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue