a relay serving broken json should not block discovery of others

This commit is contained in:
B. Petersen
2026-08-12 11:32:59 +02:00
parent 3b8aca042d
commit 340cb9c34c
2 changed files with 25 additions and 8 deletions
@@ -13,7 +13,7 @@ pub struct JsonrpcAppSource {
pub version_string: String, pub version_string: String,
/// Where to download that version. /// Where to download that version.
/// Security note: consumers need to verify themselves /// Security note: consumers need to verify themselves
/// that downloaded app files are valid before installing them. /// that downloaded app files are valid before installing them.
pub download_url: String, pub download_url: String,
} }
+24 -7
View File
@@ -4,6 +4,7 @@
//! The version information comes in via IMAP METADATA, //! The version information comes in via IMAP METADATA,
//! (as JSON) and is parsed to `AppVersionInfo`. //! (as JSON) and is parsed to `AppVersionInfo`.
use crate::accounts::Accounts; use crate::accounts::Accounts;
use crate::log::warn;
use anyhow::Result; use anyhow::Result;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -65,7 +66,13 @@ pub async fn get_app_version(
let Some(json) = &metadata.app_versions else { let Some(json) = &metadata.app_versions else {
continue; continue;
}; };
let app_versions: AppVersionInfo = serde_json::from_str(json)?; let app_versions: AppVersionInfo = match serde_json::from_str(json) {
Ok(app_versions) => app_versions,
Err(err) => {
warn!(context, "Failed to parse appversions: {err:#}.");
continue;
}
};
let candidate = app_versions let candidate = app_versions
.clients .clients
.into_iter() .into_iter()
@@ -166,7 +173,7 @@ mod tests {
assert!(version.is_none()); assert!(version.is_none());
// first account reports two clients, with one and two sources // first account reports two clients, with one and two sources
let account_id = accounts.add_account().await?; let account_id1 = accounts.add_account().await?;
let json = r##"{ let json = r##"{
"clients": [ "clients": [
{ {
@@ -199,7 +206,7 @@ mod tests {
} }
] ]
}"##; }"##;
mockup_app_versions(&accounts, account_id, json).await; mockup_app_versions(&accounts, account_id1, json).await;
let version = get_app_version(&accounts, "basta", "web").await?.unwrap(); let version = get_app_version(&accounts, "basta", "web").await?.unwrap();
assert_eq!(version.version_integer, 754); assert_eq!(version.version_integer, 754);
@@ -220,7 +227,7 @@ mod tests {
assert!(version.is_none()); assert!(version.is_none());
// a second account reports a newer version for "bar" // a second account reports a newer version for "bar"
let account_id = accounts.add_account().await?; let account_id2 = accounts.add_account().await?;
let json = r##"{ let json = r##"{
"clients": [ "clients": [
{ {
@@ -236,7 +243,7 @@ mod tests {
} }
] ]
}"##; }"##;
mockup_app_versions(&accounts, account_id, json).await; mockup_app_versions(&accounts, account_id2, json).await;
let version = get_app_version(&accounts, "basta", "web").await?.unwrap(); let version = get_app_version(&accounts, "basta", "web").await?.unwrap();
assert_eq!(version.version_integer, 754); assert_eq!(version.version_integer, 754);
@@ -257,7 +264,7 @@ mod tests {
assert!(version.is_none()); assert!(version.is_none());
// a third account reports a older version for "bar", that is ignored // a third account reports a older version for "bar", that is ignored
let account_id = accounts.add_account().await?; let account_id3 = accounts.add_account().await?;
let json = r##"{ let json = r##"{
"clients": [ "clients": [
{ {
@@ -273,7 +280,7 @@ mod tests {
} }
] ]
}"##; }"##;
mockup_app_versions(&accounts, account_id, json).await; mockup_app_versions(&accounts, account_id3, json).await;
let version = get_app_version(&accounts, "basta", "web").await?.unwrap(); let version = get_app_version(&accounts, "basta", "web").await?.unwrap();
assert_eq!(version.version_integer, 754); assert_eq!(version.version_integer, 754);
@@ -293,6 +300,16 @@ mod tests {
let version = get_app_version(&accounts, "non-", "existant").await?; let version = get_app_version(&accounts, "non-", "existant").await?;
assert!(version.is_none()); assert!(version.is_none());
// second account returns an invalid json, that account is skipped, but app versionss are still gathered from the other
let account_id2 = accounts.add_account().await?;
let json = r"bad json!";
mockup_app_versions(&accounts, account_id2, json).await;
let version = get_app_version(&accounts, "foo", "bar").await?.unwrap();
assert_eq!(version.version_integer, 42);
assert_eq!(version.version_string, "42.0");
assert_eq!(version.download_url, "https://foo.bar/42.0.prg");
Ok(()) Ok(())
} }
} }