From 97e24d0d41bb743833e457de5ba49c5c233eb3b3 Mon Sep 17 00:00:00 2001 From: Ellie Huxtable Date: Fri, 14 Jul 2023 20:44:08 +0100 Subject: Add new sync (#1093) * Add record migration * Add database functions for inserting history No real tests yet :( I would like to avoid running postgres lol * Add index handler, use UUIDs not strings * Fix a bunch of tests, remove Option * Add tests, all passing * Working upload sync * Record downloading works * Sync download works * Don't waste requests * Use a page size for uploads, make it variable later * Aaaaaand they're encrypted now too * Add cek * Allow reading tail across hosts * Revert "Allow reading tail across hosts" Not like that This reverts commit 7b0c72e7e050c358172f9b53cbd21b9e44cf4931. * Handle multiple shards properly * format * Format and make clippy happy * use some fancy types (#1098) * use some fancy types * fmt * Goodbye horrible tuple * Update atuin-server-postgres/migrations/20230623070418_records.sql Co-authored-by: Conrad Ludgate * fmt * Sort tests too because time sucks * fix features --------- Co-authored-by: Conrad Ludgate --- atuin-server/src/handlers/record.rs | 104 ++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 atuin-server/src/handlers/record.rs (limited to 'atuin-server/src/handlers/record.rs') diff --git a/atuin-server/src/handlers/record.rs b/atuin-server/src/handlers/record.rs new file mode 100644 index 00000000..0100c693 --- /dev/null +++ b/atuin-server/src/handlers/record.rs @@ -0,0 +1,104 @@ +use axum::{extract::Query, extract::State, Json}; +use http::StatusCode; +use serde::Deserialize; +use tracing::{error, instrument}; + +use super::{ErrorResponse, ErrorResponseStatus, RespExt}; +use crate::router::{AppState, UserAuth}; +use atuin_server_database::Database; + +use atuin_common::record::{EncryptedData, HostId, Record, RecordId, RecordIndex}; + +#[instrument(skip_all, fields(user.id = user.id))] +pub async fn post( + UserAuth(user): UserAuth, + state: State>, + Json(records): Json>>, +) -> Result<(), ErrorResponseStatus<'static>> { + let State(AppState { database, settings }) = state; + + tracing::debug!( + count = records.len(), + user = user.username, + "request to add records" + ); + + let too_big = records + .iter() + .any(|r| r.data.data.len() >= settings.max_record_size || settings.max_record_size == 0); + + if too_big { + 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))] +pub async fn index( + UserAuth(user): UserAuth, + state: State>, +) -> Result, ErrorResponseStatus<'static>> { + let State(AppState { + database, + settings: _, + }) = state; + + let record_index = match database.tail_records(&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)); + } + }; + + Ok(Json(record_index)) +} + +#[derive(Deserialize)] +pub struct NextParams { + host: HostId, + tag: String, + start: Option, + count: u64, +} + +#[instrument(skip_all, fields(user.id = user.id))] +pub async fn next( + params: Query, + UserAuth(user): UserAuth, + state: State>, +) -> Result>>, 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)); + } + }; + + Ok(Json(records)) +} -- cgit v1.3.1