about summary refs log tree commit diff
path: root/src/indieauth
diff options
context:
space:
mode:
authorVika <vika@fireburn.ru>2024-08-18 00:17:54 +0300
committerVika <vika@fireburn.ru>2024-08-18 00:27:53 +0300
commit90d2e2d20928d06ab971090dc22ddff267e80d39 (patch)
treec21a11d6d1b4285628ac6534e3f613888c4ab743 /src/indieauth
parent1bf23d1c2dd6e85c677392a83a67a581c218cc11 (diff)
downloadkittybox-90d2e2d20928d06ab971090dc22ddff267e80d39.tar.zst
indieauth: fix profile fetching if some properties are undeclared
Diffstat (limited to 'src/indieauth')
-rw-r--r--src/indieauth/mod.rs42
1 files changed, 23 insertions, 19 deletions
diff --git a/src/indieauth/mod.rs b/src/indieauth/mod.rs
index 9f35ed0..808b9b7 100644
--- a/src/indieauth/mod.rs
+++ b/src/indieauth/mod.rs
@@ -719,33 +719,37 @@ async fn revocation_endpoint_post<A: AuthBackend>(
     }
 }
 
+#[tracing::instrument(skip(db))]
 async fn get_profile<D: Storage + 'static>(
     db: D,
     url: &str,
     email: bool
 ) -> crate::database::Result<Option<Profile>> {
+    fn get_first(v: serde_json::Value) -> Option<String> {
+        match v {
+            serde_json::Value::Array(mut a) => {
+                a.truncate(1);
+                match a.pop() {
+                    Some(serde_json::Value::String(s)) => Some(s),
+                    Some(serde_json::Value::Object(mut o)) => o.remove("value").and_then(get_first),
+                    _ => None
+                }
+            },
+            _ => None
+        }
+    }
+
     Ok(db.get_post(url).await?.map(|mut mf2| {
         // Ruthlessly manually destructure the MF2 document to save memory
-        let name = match mf2["properties"]["name"][0].take() {
-            serde_json::Value::String(s) => Some(s),
-            _ => None
-        };
-        let url = match mf2["properties"]["uid"][0].take() {
-            serde_json::Value::String(s) => s.parse().ok(),
-            _ => None
-        };
-        let photo = match mf2["properties"]["photo"][0].take() {
-            serde_json::Value::String(s) => s.parse().ok(),
-            _ => None
-        };
-        let email = if email {
-            match mf2["properties"]["email"][0].take() {
-                serde_json::Value::String(s) => Some(s),
-                _ => None
-            }
-        } else {
-            None
+        let mut properties = match mf2.as_object_mut().unwrap().remove("properties") {
+            Some(serde_json::Value::Object(props)) => props,
+            _ => unreachable!()
         };
+        drop(mf2);
+        let name = properties.remove("name").and_then(get_first);
+        let url = properties.remove("uid").and_then(get_first).and_then(|u| u.parse().ok());
+        let photo = properties.remove("photo").and_then(get_first).and_then(|u| u.parse().ok());
+        let email = properties.remove("name").and_then(get_first);
 
         Profile { name, url, photo, email }
     }))