aboutsummaryrefslogtreecommitdiffstats
path: root/atuin-server/src/handlers/history.rs
diff options
context:
space:
mode:
authorEllie Huxtable <e@elm.sh>2021-04-20 21:53:07 +0100
committerGitHub <noreply@github.com>2021-04-20 20:53:07 +0000
commita21737e2b7f8d1e426726bdd7536033f299d476a (patch)
treee940afdff9c145d25d9a2895fd44a77d70719a2e /atuin-server/src/handlers/history.rs
parentSwitch to Warp + SQLx, use async, switch to Rust stable (#36) (diff)
downloadatuin-a21737e2b7f8d1e426726bdd7536033f299d476a.zip
Use cargo workspaces (#37)
* Switch to Cargo workspaces Breaking things into "client", "server" and "common" makes managing the codebase much easier! client - anything running on a user's machine for adding history server - handles storing/syncing history and running a HTTP server common - request/response API definitions, common utils, etc * Update dockerfile
Diffstat (limited to 'atuin-server/src/handlers/history.rs')
-rw-r--r--atuin-server/src/handlers/history.rs89
1 files changed, 89 insertions, 0 deletions
diff --git a/atuin-server/src/handlers/history.rs b/atuin-server/src/handlers/history.rs
new file mode 100644
index 00000000..1aebdde1
--- /dev/null
+++ b/atuin-server/src/handlers/history.rs
@@ -0,0 +1,89 @@
+use std::convert::Infallible;
+
+use warp::{http::StatusCode, reply::json};
+
+use crate::database::Database;
+use crate::models::{NewHistory, User};
+use atuin_common::api::{
+ AddHistoryRequest, CountResponse, ErrorResponse, SyncHistoryRequest, SyncHistoryResponse,
+};
+
+pub async fn count(
+ user: User,
+ db: impl Database + Clone + Send + Sync,
+) -> Result<Box<dyn warp::Reply>, Infallible> {
+ db.count_history(&user).await.map_or(
+ Ok(Box::new(ErrorResponse::reply(
+ "failed to query history count",
+ StatusCode::INTERNAL_SERVER_ERROR,
+ ))),
+ |count| Ok(Box::new(json(&CountResponse { count }))),
+ )
+}
+
+pub async fn list(
+ req: SyncHistoryRequest,
+ user: User,
+ db: impl Database + Clone + Send + Sync,
+) -> Result<Box<dyn warp::Reply>, Infallible> {
+ let history = db
+ .list_history(
+ &user,
+ req.sync_ts.naive_utc(),
+ req.history_ts.naive_utc(),
+ req.host,
+ )
+ .await;
+
+ if let Err(e) = history {
+ error!("failed to load history: {}", e);
+ let resp =
+ ErrorResponse::reply("failed to load history", StatusCode::INTERNAL_SERVER_ERROR);
+ let resp = Box::new(resp);
+ return Ok(resp);
+ }
+
+ let history: Vec<String> = history
+ .unwrap()
+ .iter()
+ .map(|i| i.data.to_string())
+ .collect();
+
+ debug!(
+ "loaded {} items of history for user {}",
+ history.len(),
+ user.id
+ );
+
+ Ok(Box::new(json(&SyncHistoryResponse { history })))
+}
+
+pub async fn add(
+ req: Vec<AddHistoryRequest>,
+ user: User,
+ db: impl Database + Clone + Send + Sync,
+) -> Result<Box<dyn warp::Reply>, Infallible> {
+ debug!("request to add {} history items", req.len());
+
+ let history: Vec<NewHistory> = req
+ .iter()
+ .map(|h| NewHistory {
+ client_id: h.id.as_str(),
+ user_id: user.id,
+ hostname: h.hostname.as_str(),
+ timestamp: h.timestamp.naive_utc(),
+ data: h.data.as_str(),
+ })
+ .collect();
+
+ if let Err(e) = db.add_history(&history).await {
+ error!("failed to add history: {}", e);
+
+ return Ok(Box::new(ErrorResponse::reply(
+ "failed to add history",
+ StatusCode::INTERNAL_SERVER_ERROR,
+ )));
+ };
+
+ Ok(Box::new(warp::reply()))
+}