aboutsummaryrefslogtreecommitdiffstats
path: root/atuin-server/src/router.rs
diff options
context:
space:
mode:
authorEllie Huxtable <ellie@elliehuxtable.com>2024-04-18 16:41:28 +0100
committerGitHub <noreply@github.com>2024-04-18 16:41:28 +0100
commit95cc472037fcb3207b510e67f1a44af4e2a2cae9 (patch)
treefc1d3e71d8e0bdb806370e4144fd6f373bcc9c5e /atuin-server/src/router.rs
parentfeat: show preview auto (#1804) (diff)
downloadatuin-95cc472037fcb3207b510e67f1a44af4e2a2cae9.zip
chore: move crates into crates/ dir (#1958)
I'd like to tidy up the root a little, and it's nice to have all the rust crates in one place
Diffstat (limited to 'atuin-server/src/router.rs')
-rw-r--r--atuin-server/src/router.rs149
1 files changed, 0 insertions, 149 deletions
diff --git a/atuin-server/src/router.rs b/atuin-server/src/router.rs
deleted file mode 100644
index 96dff2bd..00000000
--- a/atuin-server/src/router.rs
+++ /dev/null
@@ -1,149 +0,0 @@
-use async_trait::async_trait;
-use atuin_common::api::{ErrorResponse, ATUIN_CARGO_VERSION, ATUIN_HEADER_VERSION};
-use axum::{
- extract::{FromRequestParts, Request},
- http::{self, request::Parts},
- middleware::Next,
- response::{IntoResponse, Response},
- routing::{delete, get, patch, post},
- Router,
-};
-use eyre::Result;
-use tower::ServiceBuilder;
-use tower_http::trace::TraceLayer;
-
-use super::handlers;
-use crate::{
- handlers::{ErrorResponseStatus, RespExt},
- metrics,
- settings::Settings,
-};
-use atuin_server_database::{models::User, Database, DbError};
-
-pub struct UserAuth(pub User);
-
-#[async_trait]
-impl<DB: Send + Sync> FromRequestParts<AppState<DB>> for UserAuth
-where
- DB: Database,
-{
- type Rejection = ErrorResponseStatus<'static>;
-
- async fn from_request_parts(
- req: &mut Parts,
- state: &AppState<DB>,
- ) -> 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)
- })?;
-
- if typ != "Token" {
- return Err(
- ErrorResponse::reply("invalid authorization header encoding")
- .with_status(http::StatusCode::BAD_REQUEST),
- );
- }
-
- 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)
- }
- })?;
-
- Ok(UserAuth(user))
- }
-}
-
-async fn teapot() -> impl IntoResponse {
- // This used to return 418: 🫖
- // Much as it was fun, it wasn't as useful or informative as it should be
- (http::StatusCode::NOT_FOUND, "404 not found")
-}
-
-async fn clacks_overhead(request: Request, next: Next) -> Response {
- let mut response = next.run(request).await;
-
- let gnu_terry_value = "GNU Terry Pratchett, Kris Nova";
- let gnu_terry_header = "X-Clacks-Overhead";
-
- response
- .headers_mut()
- .insert(gnu_terry_header, gnu_terry_value.parse().unwrap());
- response
-}
-
-/// Ensure that we only try and sync with clients on the same major version
-async fn semver(request: Request, next: Next) -> Response {
- let mut response = next.run(request).await;
- response
- .headers_mut()
- .insert(ATUIN_HEADER_VERSION, ATUIN_CARGO_VERSION.parse().unwrap());
-
- response
-}
-
-#[derive(Clone)]
-pub struct AppState<DB: Database> {
- pub database: DB,
- pub settings: Settings<DB::Settings>,
-}
-
-pub fn router<DB: Database>(database: DB, settings: Settings<DB::Settings>) -> Router {
- let routes = Router::new()
- .route("/", get(handlers::index))
- .route("/sync/count", get(handlers::history::count))
- .route("/sync/history", get(handlers::history::list))
- .route("/sync/calendar/:focus", get(handlers::history::calendar))
- .route("/sync/status", get(handlers::status::status))
- .route("/history", post(handlers::history::add))
- .route("/history", delete(handlers::history::delete))
- .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::<DB>))
- .route("/record", get(handlers::record::index::<DB>))
- .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));
-
- let path = settings.path.as_str();
- if path.is_empty() {
- routes
- } else {
- Router::new().nest(path, routes)
- }
- .fallback(teapot)
- .with_state(AppState { database, settings })
- .layer(
- ServiceBuilder::new()
- .layer(axum::middleware::from_fn(clacks_overhead))
- .layer(TraceLayer::new_for_http())
- .layer(axum::middleware::from_fn(metrics::track_metrics))
- .layer(axum::middleware::from_fn(semver)),
- )
-}