Idiomatic axum cleanups: named Auth field, cfg guard, drop local Either
- Auth extractor: replace bare bool tuple field with named `authenticated`
field and `is_authenticated()` method so call sites read clearly
- main.rs: guard the `inject_dev_user` branch with `#[cfg(feature = "dev")]`
so non-dev builds don't reference the cfg-gated symbol and fail to compile
- tree.rs: remove local `Either<L, R>` enum; use `Result<TreeData, FileData>`
(Ok = directory, Err = file) as the two-variant discriminant instead
https://claude.ai/code/session_013nzzxsm19t84xnUDroLyt3
diff --git a/quire-server/src/bin/quire/main.rs b/quire-server/src/bin/quire/main.rs
index 18ac4ad..8b05070 100644
--- a/quire-server/src/bin/quire/main.rs
+++ b/quire-server/src/bin/quire/main.rs
@@ -151,13 +151,15 @@ async fn main() -> Result<()> {
quire::quire::web::auth::require_auth,
));
let merged = public.merge(ci);
- if dev {
+ #[cfg(feature = "dev")]
+ let merged = if dev {
merged.layer(axum::middleware::from_fn(
quire::quire::web::auth::inject_dev_user,
))
} else {
merged
- }
+ };
+ merged
};
let api_routes = quire::quire::web::api::router(quire.clone());
commands::serve::run(&quire, web_routes, api_routes).await?
diff --git a/quire-server/src/quire/web/auth.rs b/quire-server/src/quire/web/auth.rs
index a6c08ab..e9c68f3 100644
--- a/quire-server/src/quire/web/auth.rs
+++ b/quire-server/src/quire/web/auth.rs
@@ -8,14 +8,24 @@ use axum::http::request::Parts;
use axum::middleware::Next;
use axum::response::{IntoResponse, Response};
-/// Extractor that resolves to `true` when the `Remote-User` header is present.
-pub struct Auth(pub bool);
+/// Extractor that resolves to whether the request carries a `Remote-User` header.
+pub struct Auth {
+ pub authenticated: bool,
+}
+
+impl Auth {
+ pub fn is_authenticated(&self) -> bool {
+ self.authenticated
+ }
+}
impl<S: Send + Sync> FromRequestParts<S> for Auth {
type Rejection = Infallible;
async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
- Ok(Auth(parts.headers.contains_key("Remote-User")))
+ Ok(Auth {
+ authenticated: parts.headers.contains_key("Remote-User"),
+ })
}
}
diff --git a/quire-server/src/quire/web/handlers/repo.rs b/quire-server/src/quire/web/handlers/repo.rs
index 175273c..7a25707 100644
--- a/quire-server/src/quire/web/handlers/repo.rs
+++ b/quire-server/src/quire/web/handlers/repo.rs
@@ -57,7 +57,7 @@ pub async fn repo_home(
.unwrap_or_default();
let tmpl = RepoHomeTemplate {
- sections: nav_sections(&repo_display, "overview", auth.0),
+ sections: nav_sections(&repo_display, "overview", auth.is_authenticated()),
repo: repo_display,
crumbs: vec![],
head,
diff --git a/quire-server/src/quire/web/handlers/tree.rs b/quire-server/src/quire/web/handlers/tree.rs
index 50fe98a..5c7d146 100644
--- a/quire-server/src/quire/web/handlers/tree.rs
+++ b/quire-server/src/quire/web/handlers/tree.rs
@@ -18,7 +18,7 @@ pub async fn tree_view(
auth: Auth,
AxumPath(repo): AxumPath<String>,
) -> Response {
- tree_or_file_at_path(quire, repo, String::new(), auth.0).await
+ tree_or_file_at_path(quire, repo, String::new(), auth.is_authenticated()).await
}
pub async fn tree_view_path(
@@ -26,7 +26,7 @@ pub async fn tree_view_path(
auth: Auth,
AxumPath((repo, path)): AxumPath<(String, String)>,
) -> Response {
- tree_or_file_at_path(quire, repo, path, auth.0).await
+ tree_or_file_at_path(quire, repo, path, auth.is_authenticated()).await
}
async fn tree_or_file_at_path(quire: Quire, repo: String, path: String, authed: bool) -> Response {
@@ -46,17 +46,17 @@ async fn tree_or_file_at_path(quire: Quire, repo: String, path: String, authed:
let bookmarks = reader.bookmarks();
let tags = reader.tags();
let recent_changes = reader.recent_changes_for(Some(&path_clone));
- Some(Either::Left((tree_data, bookmarks, tags, recent_changes)))
+ Some(Ok((tree_data, bookmarks, tags, recent_changes)))
} else {
// ls-tree failed — try reading as a file blob.
- read_file_data(&reader, &path_clone).map(Either::Right)
+ read_file_data(&reader, &path_clone).map(Err)
}
})
.await
.unwrap_or(None);
match result {
- Some(Either::Left((tree_data, bookmarks, tags, recent_changes))) => {
+ Some(Ok((tree_data, bookmarks, tags, recent_changes))) => {
let crumbs = build_tree_crumbs(&repo_display, &path);
let tmpl = TreeTemplate {
sections: nav_sections(&repo_display, "tree", authed),
@@ -72,7 +72,7 @@ async fn tree_or_file_at_path(quire: Quire, repo: String, path: String, authed:
};
render(&tmpl)
}
- Some(Either::Right(file_data)) => {
+ Some(Err(file_data)) => {
let crumbs = build_file_crumbs(&repo_display, &path);
let line_nums: Vec<usize> = (1..=file_data.line_count).collect();
let tmpl = FileViewTemplate {
@@ -105,11 +105,6 @@ async fn tree_or_file_at_path(quire: Quire, repo: String, path: String, authed:
}
}
-enum Either<L, R> {
- Left(L),
- Right(R),
-}
-
// ── Tree (directory) view ──────────────────────────────────────
struct TreeData {