From 2e9c292bb989ffff2c99aa2a6062962c913b3586 Mon Sep 17 00:00:00 2001 From: Vika Date: Tue, 9 Jul 2024 22:43:21 +0300 Subject: database: use Url to represent user authorities This makes the interface more consistent and resistant to misuse. --- src/frontend/mod.rs | 52 ++++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 24 deletions(-) (limited to 'src/frontend/mod.rs') diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index 7a43532..0292171 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -87,7 +87,7 @@ impl std::fmt::Display for FrontendError { #[tracing::instrument(skip(post), fields(post = %post))] pub fn filter_post( mut post: serde_json::Value, - user: Option<&str>, + user: Option<&url::Url>, ) -> Option { if post["properties"]["deleted"][0].is_string() { tracing::debug!("Deleted post; returning tombstone instead"); @@ -108,7 +108,9 @@ pub fn filter_post( serde_json::Value::String(ref author) => author.as_str(), mf2 => mf2["properties"]["uid"][0].as_str().unwrap() } - }).collect::>(); + }) + .map(|i| i.parse().unwrap()) + .collect::>(); let visibility = post["properties"]["visibility"][0] .as_str() .unwrap_or("public"); @@ -118,12 +120,12 @@ pub fn filter_post( .as_array() .unwrap_or(&empty_vec) .iter() - .map(|i| i.as_str().unwrap())); + .map(|i| i.as_str().unwrap().parse().unwrap())); audience }; tracing::debug!("post audience = {:?}", audience); - if (visibility == "private" && !audience.iter().any(|i| Some(*i) == user)) + if (visibility == "private" && !audience.iter().any(|i| Some(i) == user)) || (visibility == "protected" && user.is_none()) { return None; @@ -137,8 +139,8 @@ pub fn filter_post( .as_array() .unwrap_or(&empty_vec) .iter() - .map(|i| i.as_str().unwrap()); - if (location_visibility == "private" && !author.any(|i| Some(i) == user)) + .map(|i| i.as_str().unwrap().parse().unwrap()); + if (location_visibility == "private" && !author.any(|i| Some(&i) == user)) || (location_visibility == "protected" && user.is_none()) { post["properties"] @@ -184,10 +186,10 @@ async fn get_post_from_database( db: &S, url: &str, after: Option, - user: &Option, + user: Option<&url::Url>, ) -> std::result::Result<(serde_json::Value, Option), FrontendError> { match db - .read_feed_with_cursor(url, after.as_deref(), POSTS_PER_PAGE, user.as_deref()) + .read_feed_with_cursor(url, after.as_deref(), POSTS_PER_PAGE, user) .await { Ok(result) => match result { @@ -240,12 +242,13 @@ pub async fn homepage( Extension(db): Extension, ) -> impl IntoResponse { let user = None; // TODO authentication - let path = format!("https://{}/", host); + // This is stupid, but there is no other way. + let hcard_url: url::Url = format!("https://{}/", host).parse().unwrap(); let feed_path = format!("https://{}/feeds/main", host); match tokio::try_join!( - get_post_from_database(&db, &path, None, &user), - get_post_from_database(&db, &feed_path, query.after, &user) + get_post_from_database(&db, &hcard_url.as_str(), None, user.as_ref()), + get_post_from_database(&db, &feed_path, query.after, user.as_ref()) ) { Ok(((hcard, _), (hfeed, cursor))) => { // Here, we know those operations can't really fail @@ -254,13 +257,13 @@ pub async fn homepage( // // btw is it more efficient to fetch these in parallel? let (blogname, webring, channels) = tokio::join!( - db.get_setting::(&host) + db.get_setting::(&hcard_url) .map(Result::unwrap_or_default), - db.get_setting::(&host) + db.get_setting::(&hcard_url) .map(Result::unwrap_or_default), - db.get_channels(&host).map(|i| i.unwrap_or_default()) + db.get_channels(&hcard_url).map(|i| i.unwrap_or_default()) ); // Render the homepage ( @@ -273,7 +276,7 @@ pub async fn homepage( title: blogname.as_ref(), blog_name: blogname.as_ref(), feeds: channels, - user, + user: user.as_ref().map(url::Url::to_string), content: MainPage { feed: &hfeed, card: &hcard, @@ -298,10 +301,10 @@ pub async fn homepage( error!("Error while fetching h-card and/or h-feed: {}", err); // Return the error let (blogname, channels) = tokio::join!( - db.get_setting::(&host) + db.get_setting::(&hcard_url) .map(Result::unwrap_or_default), - db.get_channels(&host).map(|i| i.unwrap_or_default()) + db.get_channels(&hcard_url).map(|i| i.unwrap_or_default()) ); ( @@ -314,7 +317,7 @@ pub async fn homepage( title: blogname.as_ref(), blog_name: blogname.as_ref(), feeds: channels, - user, + user: user.as_ref().map(url::Url::to_string), content: ErrorPage { code: err.code(), msg: Some(err.msg().to_string()), @@ -335,13 +338,14 @@ pub async fn catchall( Query(query): Query, uri: Uri, ) -> impl IntoResponse { - let user = None; // TODO authentication - let path = url::Url::parse(&format!("https://{}/", host)) - .unwrap() + let user: Option = None; // TODO authentication + let host = url::Url::parse(&format!("https://{}/", host)).unwrap(); + let path = host + .clone() .join(uri.path()) .unwrap(); - match get_post_from_database(&db, path.as_str(), query.after, &user).await { + match get_post_from_database(&db, path.as_str(), query.after, user.as_ref()).await { Ok((post, cursor)) => { let (blogname, channels) = tokio::join!( db.get_setting::(&host) @@ -360,7 +364,7 @@ pub async fn catchall( title: blogname.as_ref(), blog_name: blogname.as_ref(), feeds: channels, - user, + user: user.as_ref().map(url::Url::to_string), content: match post.pointer("/type/0").and_then(|i| i.as_str()) { Some("h-entry") => Entry { post: &post }.to_string(), Some("h-feed") => Feed { feed: &post, cursor: cursor.as_deref() }.to_string(), @@ -390,7 +394,7 @@ pub async fn catchall( title: blogname.as_ref(), blog_name: blogname.as_ref(), feeds: channels, - user, + user: user.as_ref().map(url::Url::to_string), content: ErrorPage { code: err.code(), msg: Some(err.msg().to_owned()), -- cgit 1.4.1