about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock26
-rw-r--r--Cargo.toml7
-rw-r--r--src/frontend/mod.rs4
-rw-r--r--src/frontend/onboarding.rs3
-rw-r--r--src/indieauth/mod.rs19
-rw-r--r--src/indieauth/webauthn.rs4
-rw-r--r--src/lib.rs37
-rw-r--r--src/login.rs4
-rw-r--r--src/main.rs2
-rw-r--r--src/media/mod.rs5
-rw-r--r--src/micropub/mod.rs12
11 files changed, 61 insertions, 62 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 432e1ba..bc54f91 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -329,14 +329,14 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
 
 [[package]]
 name = "axum"
-version = "0.7.9"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
+checksum = "6d6fd624c75e18b3b4c6b9caf42b1afe24437daaee904069137d8bab077be8b8"
 dependencies = [
- "async-trait",
  "axum-core",
  "axum-macros",
  "bytes",
+ "form_urlencoded",
  "futures-util",
  "http",
  "http-body",
@@ -365,11 +365,10 @@ dependencies = [
 
 [[package]]
 name = "axum-core"
-version = "0.4.5"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199"
+checksum = "df1362f362fd16024ae199c1970ce98f9661bf5ef94b9808fee734bc3698b733"
 dependencies = [
- "async-trait",
  "bytes",
  "futures-util",
  "http",
@@ -386,22 +385,20 @@ dependencies = [
 
 [[package]]
 name = "axum-extra"
-version = "0.9.6"
+version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c794b30c904f0a1c2fb7740f7df7f7972dfaa14ef6f57cb6178dc63e5dca2f04"
+checksum = "460fc6f625a1f7705c6cf62d0d070794e94668988b1c38111baeec177c715f7b"
 dependencies = [
  "axum",
  "axum-core",
  "bytes",
  "cookie",
- "fastrand",
  "futures-util",
  "headers",
  "http",
  "http-body",
  "http-body-util",
  "mime",
- "multer",
  "pin-project-lite",
  "serde",
  "tower",
@@ -411,9 +408,9 @@ dependencies = [
 
 [[package]]
 name = "axum-macros"
-version = "0.4.2"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce"
+checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1873,7 +1870,6 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "argon2",
- "async-trait",
  "axum",
  "axum-extra",
  "bytes",
@@ -2157,9 +2153,9 @@ dependencies = [
 
 [[package]]
 name = "matchit"
-version = "0.7.3"
+version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
+checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
 
 [[package]]
 name = "md-5"
diff --git a/Cargo.toml b/Cargo.toml
index 9d4ba86..20d0f89 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -59,8 +59,8 @@ members = [".", "./util", "./templates", "./indieauth", "./templates-neo", "./to
 default-members = [".", "./util", "./templates", "./indieauth"]
 
 [workspace.dependencies]
-axum = "0.7.9"
-axum-core = "0.4.5"
+axum = "0.8.1"
+axum-core = "0.5.0"
 chrono = { version = "0.4.39", features = ["serde"] }
 clap = "4.5.23"
 data-encoding = "2.6.0"
@@ -124,9 +124,8 @@ wiremock = "0.6.2"
 [dependencies]
 anyhow = { version = "1.0.95", optional = true }
 argon2 = { version = "0.5.3", features = ["std"] }
-async-trait = "0.1.83"
 axum = { workspace = true, features = ["multipart", "json", "form", "macros"] }
-axum-extra = { version = "0.9.6", features = ["cookie", "cookie-signed", "typed-header"] }
+axum-extra = { version = "0.10.0", features = ["cookie", "cookie-signed", "typed-header"] }
 bytes = "1.9.0"
 chrono = { workspace = true }
 clap = { workspace = true, features = ["derive"], optional = true }
diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs
index 9abbcf1..8338ac6 100644
--- a/src/frontend/mod.rs
+++ b/src/frontend/mod.rs
@@ -1,10 +1,10 @@
 use crate::database::{Storage, StorageError};
 use axum::{
-    extract::{Host, Query, State},
+    extract::{Query, State},
     http::{StatusCode, Uri},
     response::IntoResponse,
 };
-use axum_extra::headers::HeaderMapExt;
+use axum_extra::{extract::Host, headers::HeaderMapExt};
 use futures_util::FutureExt;
 use serde::Deserialize;
 use std::convert::TryInto;
diff --git a/src/frontend/onboarding.rs b/src/frontend/onboarding.rs
index a8d2ae6..4588157 100644
--- a/src/frontend/onboarding.rs
+++ b/src/frontend/onboarding.rs
@@ -2,11 +2,12 @@ use std::sync::Arc;
 
 use crate::database::{settings, Storage};
 use axum::{
-    extract::{FromRef, Host, State},
+    extract::{FromRef, State},
     http::StatusCode,
     response::{Html, IntoResponse},
     Json,
 };
+use axum_extra::extract::Host;
 use kittybox_frontend_renderer::{ErrorPage, OnboardingPage, Template};
 use serde::Deserialize;
 use tokio::{task::JoinSet, sync::Mutex};
diff --git a/src/indieauth/mod.rs b/src/indieauth/mod.rs
index 0ac3dfd..ab38715 100644
--- a/src/indieauth/mod.rs
+++ b/src/indieauth/mod.rs
@@ -3,10 +3,10 @@ use microformats::types::Class;
 use tracing::error;
 use serde::Deserialize;
 use axum::{
-    extract::{Form, FromRef, Host, Json, Query, State}, http::StatusCode, response::{Html, IntoResponse, Response}
+    extract::{Form, FromRef, Json, Query, State}, http::StatusCode, response::{Html, IntoResponse, Response}
 };
 #[cfg_attr(not(feature = "webauthn"), allow(unused_imports))]
-use axum_extra::extract::cookie::{CookieJar, Cookie};
+use axum_extra::extract::{Host, cookie::{CookieJar, Cookie}};
 use axum_extra::{headers::{authorization::Bearer, Authorization, ContentType, HeaderMapExt}, TypedHeader};
 use crate::database::Storage;
 use kittybox_indieauth::{
@@ -65,7 +65,20 @@ impl axum::response::IntoResponse for IndieAuthResourceError {
     }
 }
 
-#[async_trait::async_trait]
+impl <A: AuthBackend + FromRef<St>, St: Clone + Send + Sync + 'static> axum::extract::OptionalFromRequestParts<St> for User<A> {
+    type Rejection = <Self as axum::extract::FromRequestParts<St>>::Rejection;
+
+    async fn from_request_parts(req: &mut axum::http::request::Parts, state: &St) -> Result<Option<Self>, Self::Rejection> {
+        let res = <Self as axum::extract::FromRequestParts<St>>::from_request_parts(req, state).await;
+
+        match res {
+            Ok(user) => Ok(Some(user)),
+            Err(IndieAuthResourceError::Unauthorized) => Ok(None),
+            Err(err) => Err(err),
+        }
+    }
+}
+
 impl <A: AuthBackend + FromRef<St>, St: Clone + Send + Sync + 'static> axum::extract::FromRequestParts<St> for User<A> {
     type Rejection = IndieAuthResourceError;
 
diff --git a/src/indieauth/webauthn.rs b/src/indieauth/webauthn.rs
index b7d8c71..0757e72 100644
--- a/src/indieauth/webauthn.rs
+++ b/src/indieauth/webauthn.rs
@@ -1,9 +1,9 @@
 use axum::{
-    extract::{Json, Host},
+    extract::Json,
     response::{IntoResponse, Response},
     http::StatusCode, Extension
 };
-use axum_extra::extract::cookie::{CookieJar, Cookie};
+use axum_extra::extract::{Host, cookie::{CookieJar, Cookie}};
 use axum_extra::{TypedHeader, headers::{authorization::Bearer, Authorization}};
 
 use super::backend::AuthBackend;
diff --git a/src/lib.rs b/src/lib.rs
index 5fe3b18..e6bc24c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,8 +3,8 @@
 
 use std::sync::Arc;
 
-use axum::extract::{FromRef, FromRequestParts};
-use axum_extra::extract::{cookie::Key, SignedCookieJar};
+use axum::extract::{FromRef, FromRequestParts, OptionalFromRequestParts};
+use axum_extra::extract::{cookie::{Cookie, Key}, SignedCookieJar};
 use database::{FileStorage, PostgresStorage, Storage};
 use indieauth::backend::{AuthBackend, FileBackend as FileAuthBackend};
 use kittybox_util::queue::JobQueue;
@@ -64,36 +64,23 @@ impl axum::response::IntoResponse for NoSessionError {
     }
 }
 
-#[async_trait::async_trait]
-impl<S> FromRequestParts<S> for Session
+impl<S> OptionalFromRequestParts<S> for Session
 where
     SessionStore: FromRef<S>,
     Key: FromRef<S>,
     S: Send + Sync,
 {
-    type Rejection = NoSessionError;
+    type Rejection = std::convert::Infallible;
 
-    async fn from_request_parts(parts: &mut axum::http::request::Parts, state: &S) ->  Result<Self, Self::Rejection> {
+    async fn from_request_parts(parts: &mut axum::http::request::Parts, state: &S) ->  Result<Option<Self>, Self::Rejection> {
         let jar = SignedCookieJar::<Key>::from_request_parts(parts, state).await.unwrap();
         let session_store = SessionStore::from_ref(state).read_owned().await;
 
-        tracing::debug!("Cookie jar: {:#?}", jar);
-        let cookie = match jar.get("session_id") {
-            Some(cookie) => {
-                tracing::debug!("Session ID cookie: {}", cookie);
-                cookie
-            },
-            None => { return Err(NoSessionError) }
-        };
-
-        session_store.get(
-            &dbg!(cookie.value_trimmed())
-                .parse()
-                .map_err(|err| {
-                    tracing::error!("Error parsing cookie: {}", err);
-                    NoSessionError
-                })?
-        ).cloned().ok_or(NoSessionError)
+        Ok(jar.get("session_id")
+            .as_ref()
+            .map(Cookie::value_trimmed)
+            .and_then(|id| uuid::Uuid::parse_str(id).ok())
+            .and_then(|id| session_store.get(&id).cloned()))
     }
 }
 
@@ -264,7 +251,7 @@ pub mod companion {
 
         axum::Router::new()
             .route(
-                "/:filename",
+                "/{filename}",
                 axum::routing::get(map_to_static)
                     .layer(Extension(resources))
             )
@@ -309,7 +296,7 @@ St: Clone + Send + Sync + 'static
         .route("/.kittybox/health", get(health_check::<S>))
         .nest("/.kittybox/login", crate::login::router::<St, S>())
         .route(
-            "/.kittybox/static/:path",
+            "/.kittybox/static/{path}",
             axum::routing::get(crate::frontend::statics)
         )
         .route("/.kittybox/coffee", get(teapot_route))
diff --git a/src/login.rs b/src/login.rs
index 19bfaf7..eaa787c 100644
--- a/src/login.rs
+++ b/src/login.rs
@@ -1,8 +1,8 @@
 use std::{borrow::Cow, str::FromStr};
 
 use futures_util::FutureExt;
-use axum::{extract::{FromRef, Host, Query, State}, http::HeaderValue, response::IntoResponse, Form};
-use axum_extra::{extract::{cookie::{self, Cookie}, SignedCookieJar}, headers::HeaderMapExt, TypedHeader};
+use axum::{extract::{FromRef, Query, State}, http::HeaderValue, response::IntoResponse, Form};
+use axum_extra::{extract::{Host, cookie::{self, Cookie}, SignedCookieJar}, headers::HeaderMapExt, TypedHeader};
 use hyper::{header::{CACHE_CONTROL, LOCATION}, StatusCode};
 use kittybox_frontend_renderer::{Template, LoginPage, LogoutPage};
 use kittybox_indieauth::{AuthorizationResponse, Error, GrantType, PKCEVerifier, Scope, Scopes};
diff --git a/src/main.rs b/src/main.rs
index f57b0be..bd3684e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -224,7 +224,7 @@ async fn main() {
         }
     };
 
-    let mut servers: Vec<axum::serve::Serve<_, _>> = vec![];
+    let mut servers: Vec<axum::serve::Serve<_, _, _>> = vec![];
 
     let build_hyper = |tcp: std::net::TcpListener| {
         tracing::info!("Listening on {}", tcp.local_addr().unwrap());
diff --git a/src/media/mod.rs b/src/media/mod.rs
index 3ed6810..199f05f 100644
--- a/src/media/mod.rs
+++ b/src/media/mod.rs
@@ -1,7 +1,8 @@
 use axum::{
-    extract::{multipart::Multipart, FromRef, Host, Path, State}, response::{IntoResponse, Response}
+    extract::{multipart::Multipart, FromRef, Path, State}, response::{IntoResponse, Response}
 };
 use axum_extra::headers::{ContentLength, HeaderMapExt, HeaderValue, IfNoneMatch};
+use axum_extra::extract::Host;
 use axum_extra::TypedHeader;
 use kittybox_util::micropub::{Error as MicropubError, ErrorKind as ErrorType};
 use kittybox_indieauth::Scope;
@@ -132,5 +133,5 @@ pub fn router<St, A, M>() -> axum::Router<St> where
 {
     axum::Router::new()
         .route("/", axum::routing::post(upload::<M, A>))
-        .route("/uploads/*file", axum::routing::get(serve::<M>))
+        .route("/uploads/{*file}", axum::routing::get(serve::<M>))
 }
diff --git a/src/micropub/mod.rs b/src/micropub/mod.rs
index 621d4f9..719fbf0 100644
--- a/src/micropub/mod.rs
+++ b/src/micropub/mod.rs
@@ -6,8 +6,9 @@ use crate::database::{MicropubChannel, Storage, StorageError};
 use crate::indieauth::backend::AuthBackend;
 use crate::indieauth::User;
 use crate::micropub::util::form_to_mf2_json;
-use axum::extract::{FromRef, Host, Query, State};
+use axum::extract::{FromRef, Query, State};
 use axum::body::Body as BodyStream;
+use axum_extra::extract::Host;
 use axum_extra::headers::ContentType;
 use axum::response::{IntoResponse, Response};
 use axum_extra::TypedHeader;
@@ -603,13 +604,13 @@ pub(crate) async fn post<D: Storage + 'static, A: AuthBackend>(
 #[tracing::instrument(skip(db))]
 pub(crate) async fn query<D: Storage, A: AuthBackend>(
     State(db): State<D>,
-    query: Option<Query<MicropubQuery>>,
+    query: Result<Query<MicropubQuery>, <Query<MicropubQuery> as axum::extract::FromRequestParts<()>>::Rejection>,
     Host(host): Host,
     user: User<A>,
 ) -> axum::response::Response {
     // We handle the invalid query case manually to return a
     // MicropubError instead of HTTP 422
-    let query = if let Some(Query(query)) = query {
+    let query = if let Ok(Query(query)) = query {
         query
     } else {
         return MicropubError::from_static(
@@ -771,7 +772,8 @@ mod tests {
 
     use super::FetchedPostContext;
     use kittybox_indieauth::{Scopes, Scope, TokenData};
-    use axum::extract::{Host, State};
+    use axum::extract::State;
+    use axum_extra::extract::Host;
 
     #[test]
     fn test_populate_reply_context() {
@@ -927,7 +929,7 @@ mod tests {
     async fn test_query_foreign_url() {
         let res = super::query(
             State(crate::database::MemoryStorage::default()),
-            Some(axum::extract::Query(super::MicropubQuery::source(
+            Ok(axum::extract::Query(super::MicropubQuery::source(
                 "https://aaronparecki.com/feeds/main",
             ))),
             Host("aaronparecki.com".to_owned()),