aboutsummaryrefslogtreecommitdiffstats
path: root/crates/server/src/handlers/v0
diff options
context:
space:
mode:
Diffstat (limited to 'crates/server/src/handlers/v0')
-rw-r--r--crates/server/src/handlers/v0/mod.rs1
-rw-r--r--crates/server/src/handlers/v0/record.rs113
2 files changed, 114 insertions, 0 deletions
diff --git a/crates/server/src/handlers/v0/mod.rs b/crates/server/src/handlers/v0/mod.rs
new file mode 100644
index 00000000..78fb47b8
--- /dev/null
+++ b/crates/server/src/handlers/v0/mod.rs
@@ -0,0 +1 @@
+pub(crate) mod record;
diff --git a/crates/server/src/handlers/v0/record.rs b/crates/server/src/handlers/v0/record.rs
new file mode 100644
index 00000000..0381ded8
--- /dev/null
+++ b/crates/server/src/handlers/v0/record.rs
@@ -0,0 +1,113 @@
+use axum::{Json, extract::Query, extract::State, http::StatusCode};
+use metrics::counter;
+use serde::Deserialize;
+use tracing::{error, instrument};
+
+use crate::{
+ handlers::{ErrorResponse, ErrorResponseStatus, RespExt},
+ router::{AppState, UserAuth},
+};
+
+use crate::atuin_common::record::{EncryptedData, HostId, Record, RecordIdx, RecordStatus};
+
+#[instrument(skip_all, fields(user.id = user.id.to_string()))]
+pub(crate) async fn post(
+ UserAuth(user): UserAuth,
+ state: State<AppState>,
+ Json(records): Json<Vec<Record<EncryptedData>>>,
+) -> Result<(), ErrorResponseStatus<'static>> {
+ let State(AppState { database, settings }) = state;
+
+ tracing::debug!(
+ count = records.len(),
+ user = user.id.to_string(),
+ "request to add records"
+ );
+
+ counter!("atuin_record_uploaded").increment(records.len() as u64);
+
+ let keep = records
+ .iter()
+ .all(|r| r.data.data.len() <= settings.max_record_size || settings.max_record_size == 0);
+
+ if !keep {
+ counter!("atuin_record_too_large").increment(1);
+
+ return Err(
+ ErrorResponse::reply("could not add records; record too large")
+ .with_status(StatusCode::BAD_REQUEST),
+ );
+ }
+
+ if let Err(e) = database.add_records(&user, &records).await {
+ error!("failed to add record: {}", e);
+
+ return Err(ErrorResponse::reply("failed to add record")
+ .with_status(StatusCode::INTERNAL_SERVER_ERROR));
+ }
+
+ Ok(())
+}
+
+#[instrument(skip_all, fields(user.id = user.id.to_string()))]
+pub(crate) async fn index(
+ UserAuth(user): UserAuth,
+ state: State<AppState>,
+) -> Result<Json<RecordStatus>, ErrorResponseStatus<'static>> {
+ let State(AppState {
+ database,
+ settings: _,
+ }) = state;
+
+ let record_index = match database.status(&user).await {
+ Ok(index) => index,
+ Err(e) => {
+ error!("failed to get record index: {}", e);
+
+ return Err(ErrorResponse::reply("failed to calculate record index")
+ .with_status(StatusCode::INTERNAL_SERVER_ERROR));
+ }
+ };
+
+ tracing::debug!(user = user.id.to_string(), "record index request");
+
+ Ok(Json(record_index))
+}
+
+#[derive(Deserialize)]
+pub(crate) struct NextParams {
+ host: HostId,
+ tag: String,
+ start: Option<RecordIdx>,
+ count: u64,
+}
+
+#[instrument(skip_all, fields(user.id = user.id.to_string()))]
+pub(crate) async fn next(
+ params: Query<NextParams>,
+ UserAuth(user): UserAuth,
+ state: State<AppState>,
+) -> Result<Json<Vec<Record<EncryptedData>>>, ErrorResponseStatus<'static>> {
+ let State(AppState {
+ database,
+ settings: _,
+ }) = state;
+ let params = params.0;
+
+ let records = match database
+ .next_records(&user, params.host, params.tag, params.start, params.count)
+ .await
+ {
+ Ok(records) => records,
+ Err(e) => {
+ error!("failed to get record index: {}", e);
+
+ return Err(ErrorResponse::reply("failed to calculate record index")
+ .with_status(StatusCode::INTERNAL_SERVER_ERROR));
+ }
+ };
+
+ counter!("atuin_record_downloaded").increment(records.len() as u64);
+
+ Ok(Json(records))
+}