diff options
Diffstat (limited to 'src/server/router.rs')
-rw-r--r-- | src/server/router.rs | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/server/router.rs b/src/server/router.rs new file mode 100644 index 00000000..ed317ab2 --- /dev/null +++ b/src/server/router.rs @@ -0,0 +1,121 @@ +use std::convert::Infallible; + +use eyre::Result; +use warp::Filter; + +use super::handlers; +use super::{database::Database, database::Postgres}; +use crate::server::models::User; +use crate::{api::SyncHistoryRequest, settings::Settings}; + +fn with_settings( + settings: Settings, +) -> impl Filter<Extract = (Settings,), Error = Infallible> + Clone { + warp::any().map(move || settings.clone()) +} + +fn with_db( + db: impl Database + Clone + Send + Sync, +) -> impl Filter<Extract = (impl Database + Clone,), Error = Infallible> + Clone { + warp::any().map(move || db.clone()) +} + +fn with_user( + postgres: Postgres, +) -> impl Filter<Extract = (User,), Error = warp::Rejection> + Clone { + warp::header::<String>("authorization").and_then(move |header: String| { + // async closures are still buggy :( + let postgres = postgres.clone(); + + async move { + let header: Vec<&str> = header.split(' ').collect(); + + let token; + + if header.len() == 2 { + if header[0] != "Token" { + return Err(warp::reject()); + } + + token = header[1]; + } else { + return Err(warp::reject()); + } + + let user = postgres + .get_session_user(token) + .await + .map_err(|_| warp::reject())?; + + Ok(user) + } + }) +} + +pub async fn router( + settings: &Settings, +) -> Result<impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone> { + let postgres = Postgres::new(settings.server.db_uri.as_str()).await?; + let index = warp::get().and(warp::path::end()).map(handlers::index); + + let count = warp::get() + .and(warp::path("sync")) + .and(warp::path("count")) + .and(warp::path::end()) + .and(with_user(postgres.clone())) + .and(with_db(postgres.clone())) + .and_then(handlers::history::count); + + let sync = warp::get() + .and(warp::path("sync")) + .and(warp::path("history")) + .and(warp::query::<SyncHistoryRequest>()) + .and(warp::path::end()) + .and(with_user(postgres.clone())) + .and(with_db(postgres.clone())) + .and_then(handlers::history::list); + + let add_history = warp::post() + .and(warp::path("history")) + .and(warp::path::end()) + .and(warp::body::json()) + .and(with_user(postgres.clone())) + .and(with_db(postgres.clone())) + .and_then(handlers::history::add); + + let user = warp::get() + .and(warp::path("user")) + .and(warp::path::param::<String>()) + .and(warp::path::end()) + .and(with_db(postgres.clone())) + .and_then(handlers::user::get); + + let register = warp::post() + .and(warp::path("register")) + .and(warp::path::end()) + .and(warp::body::json()) + .and(with_settings(settings.clone())) + .and(with_db(postgres.clone())) + .and_then(handlers::user::register); + + let login = warp::post() + .and(warp::path("login")) + .and(warp::path::end()) + .and(warp::body::json()) + .and(with_db(postgres)) + .and_then(handlers::user::login); + + let r = warp::any() + .and( + index + .or(count) + .or(sync) + .or(add_history) + .or(user) + .or(register) + .or(login), + ) + .with(warp::filters::log::log("atuin::api")); + + Ok(r) +} |