aboutsummaryrefslogtreecommitdiffstats
path: root/crates/turtle/src/atuin_server/router.rs
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-06-11 18:02:55 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-06-11 18:02:55 +0200
commit0b6ca5cb8ca4c46265e08e13053260d9b5cff568 (patch)
tree9dc656095f806e6dd1177e40b9a87cf6d6f10f1b /crates/turtle/src/atuin_server/router.rs
parentchore(server): Remove the last remnants of the "hub" sync-server thingy (diff)
downloadatuin-0b6ca5cb8ca4c46265e08e13053260d9b5cff568.zip
feat(server): Make user stuff stateless
Diffstat (limited to 'crates/turtle/src/atuin_server/router.rs')
-rw-r--r--crates/turtle/src/atuin_server/router.rs74
1 files changed, 21 insertions, 53 deletions
diff --git a/crates/turtle/src/atuin_server/router.rs b/crates/turtle/src/atuin_server/router.rs
index 778e699a..dfc2cac4 100644
--- a/crates/turtle/src/atuin_server/router.rs
+++ b/crates/turtle/src/atuin_server/router.rs
@@ -1,18 +1,19 @@
use crate::{
atuin_common::api::{ATUIN_CARGO_VERSION, ATUIN_HEADER_VERSION, ErrorResponse},
- atuin_server::database::{DbError, db::Database, models::User},
+ atuin_server::database::{db::Database, models::User},
};
use axum::{
Router,
- extract::{FromRequestParts, Request},
+ extract::{FromRequestParts, Path, Request},
http::{self, request::Parts},
middleware::Next,
response::{IntoResponse, Response},
- routing::{delete, get, patch, post},
+ routing::{get, post},
};
use eyre::Result;
use tower::ServiceBuilder;
use tower_http::trace::TraceLayer;
+use uuid::Uuid;
use super::handlers;
use crate::atuin_server::{
@@ -30,42 +31,19 @@ impl FromRequestParts<AppState> for UserAuth {
req: &mut Parts,
state: &AppState,
) -> Result<Self, Self::Rejection> {
- let auth_header = req
- .headers
- .get(http::header::AUTHORIZATION)
- .ok_or_else(|| {
- ErrorResponse::reply("missing authorization header")
- .with_status(http::StatusCode::BAD_REQUEST)
- })?;
- let auth_header = auth_header.to_str().map_err(|_| {
- ErrorResponse::reply("invalid authorization header encoding")
- .with_status(http::StatusCode::BAD_REQUEST)
- })?;
- let (typ, token) = auth_header.split_once(' ').ok_or_else(|| {
- ErrorResponse::reply("invalid authorization header encoding")
- .with_status(http::StatusCode::BAD_REQUEST)
- })?;
+ let user_id = {
+ let Path(user_id) =
+ <Path<Uuid> as FromRequestParts<AppState>>::from_request_parts(req, state)
+ .await
+ .map_err(|_| {
+ ErrorResponse::reply("invalid user_id path param")
+ .with_status(http::StatusCode::BAD_REQUEST)
+ })?;
- if typ != "Token" {
- return Err(
- ErrorResponse::reply("invalid authorization header encoding")
- .with_status(http::StatusCode::BAD_REQUEST),
- );
- }
+ user_id
+ };
- let user = state
- .database
- .get_session_user(token)
- .await
- .map_err(|e| match e {
- DbError::NotFound => ErrorResponse::reply("session not found")
- .with_status(http::StatusCode::FORBIDDEN),
- DbError::Other(e) => {
- tracing::error!(error = ?e, "could not query user session");
- ErrorResponse::reply("could not query user session")
- .with_status(http::StatusCode::INTERNAL_SERVER_ERROR)
- }
- })?;
+ let user = User { id: user_id };
Ok(UserAuth(user))
}
@@ -96,22 +74,12 @@ pub(crate) struct AppState {
pub(crate) fn router(database: Database, settings: Settings) -> Router {
let routes = Router::new()
.route("/", get(handlers::index))
- .route("/healthz", get(handlers::health::health_check));
-
- let routes = routes
- .route("/user/{username}", get(handlers::user::get))
- .route("/account", delete(handlers::user::delete))
- .route("/account/password", patch(handlers::user::change_password))
- .route("/register", post(handlers::user::register))
- .route("/login", post(handlers::user::login))
- .route("/record", post(handlers::record::post))
- .route("/record", get(handlers::record::index))
- .route("/record/next", get(handlers::record::next))
- .route("/api/v0/me", get(handlers::v0::me::get))
- .route("/api/v0/record", post(handlers::v0::record::post))
- .route("/api/v0/record", get(handlers::v0::record::index))
- .route("/api/v0/record/next", get(handlers::v0::record::next))
- .route("/api/v0/store", delete(handlers::v0::store::delete));
+ .route("/api/v0/{user_id}/record", post(handlers::v0::record::post))
+ .route("/api/v0/{user_id}/record", get(handlers::v0::record::index))
+ .route(
+ "/api/v0/{user_id}/record/next",
+ get(handlers::v0::record::next),
+ );
let path = settings.path.as_str();
if path.is_empty() {