atuin/atuin-server/src/router.rs

92 lines
2.7 KiB
Rust
Raw Normal View History

2022-04-12 16:06:19 -06:00
use async_trait::async_trait;
use axum::{
2023-02-10 02:45:20 -07:00
extract::FromRequestParts,
2022-04-12 16:06:19 -06:00
response::IntoResponse,
routing::{delete, get, post},
2023-02-10 02:45:20 -07:00
Router,
2022-04-12 16:06:19 -06:00
};
use eyre::Result;
2023-02-10 02:45:20 -07:00
use http::request::Parts;
use tower::ServiceBuilder;
use tower_http::trace::TraceLayer;
use super::handlers;
use crate::settings::Settings;
use atuin_server_database::{models::User, Database};
pub struct UserAuth(pub User);
2022-04-12 16:06:19 -06:00
#[async_trait]
impl<DB: Send + Sync> FromRequestParts<AppState<DB>> for UserAuth
where
DB: Database,
{
2022-04-12 16:06:19 -06:00
type Rejection = http::StatusCode;
2023-02-10 02:45:20 -07:00
async fn from_request_parts(
req: &mut Parts,
state: &AppState<DB>,
2023-02-10 02:45:20 -07:00
) -> Result<Self, Self::Rejection> {
2022-04-12 16:06:19 -06:00
let auth_header = req
2023-02-10 02:45:20 -07:00
.headers
2022-04-12 16:06:19 -06:00
.get(http::header::AUTHORIZATION)
.ok_or(http::StatusCode::FORBIDDEN)?;
let auth_header = auth_header
.to_str()
.map_err(|_| http::StatusCode::FORBIDDEN)?;
let (typ, token) = auth_header
.split_once(' ')
.ok_or(http::StatusCode::FORBIDDEN)?;
if typ != "Token" {
return Err(http::StatusCode::FORBIDDEN);
}
2023-02-10 02:45:20 -07:00
let user = state
.database
2022-04-12 16:06:19 -06:00
.get_session_user(token)
.await
.map_err(|_| http::StatusCode::FORBIDDEN)?;
Ok(UserAuth(user))
2022-04-12 16:06:19 -06:00
}
}
2022-04-12 16:06:19 -06:00
async fn teapot() -> impl IntoResponse {
(http::StatusCode::IM_A_TEAPOT, "")
}
2023-02-10 02:45:20 -07:00
#[derive(Clone)]
pub struct AppState<DB: Database> {
pub database: DB,
pub settings: Settings<DB::Settings>,
2023-02-10 02:45:20 -07:00
}
pub fn router<DB: Database>(database: DB, settings: Settings<DB::Settings>) -> Router {
let routes = Router::new()
2022-04-12 16:06:19 -06:00
.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))
2022-04-12 16:06:19 -06:00
.route("/history", post(handlers::history::add))
.route("/history", delete(handlers::history::delete))
.route("/record", post(handlers::record::post))
.route("/record", get(handlers::record::index))
.route("/record/next", get(handlers::record::next))
2022-04-12 16:06:19 -06:00
.route("/user/:username", get(handlers::user::get))
.route("/account", delete(handlers::user::delete))
2022-04-12 16:06:19 -06:00
.route("/register", post(handlers::user::register))
.route("/login", post(handlers::user::login));
let path = settings.path.as_str();
if path.is_empty() {
routes
} else {
Router::new().nest(path, routes)
}
2023-02-10 02:45:20 -07:00
.fallback(teapot)
.with_state(AppState { database, settings })
2023-02-10 02:45:20 -07:00
.layer(ServiceBuilder::new().layer(TraceLayer::new_for_http()))
}