From 8655c93853506acf05f6ae4e58bfc2c6198be254 Mon Sep 17 00:00:00 2001 From: Conrad Ludgate Date: Mon, 12 Jun 2023 09:04:35 +0100 Subject: refactor server to allow pluggable db and tracing (#1036) * refactor server to allow pluggable db and tracing * clean up * fix descriptions * remove dependencies --- atuin-server/src/handlers/history.rs | 44 ++++++++++++++++++++++++++---------- atuin-server/src/handlers/status.rs | 5 ++-- atuin-server/src/handlers/user.rs | 22 +++++++++--------- 3 files changed, 46 insertions(+), 25 deletions(-) (limited to 'atuin-server/src/handlers') diff --git a/atuin-server/src/handlers/history.rs b/atuin-server/src/handlers/history.rs index 1c9dff5f..bb0aa321 100644 --- a/atuin-server/src/handlers/history.rs +++ b/atuin-server/src/handlers/history.rs @@ -10,18 +10,20 @@ use tracing::{debug, error, instrument}; use super::{ErrorResponse, ErrorResponseStatus, RespExt}; use crate::{ - calendar::{TimePeriod, TimePeriodInfo}, - database::Database, - models::{NewHistory, User}, - router::AppState, + router::{AppState, UserAuth}, utils::client_version_min, }; +use atuin_server_database::{ + calendar::{TimePeriod, TimePeriodInfo}, + models::NewHistory, + Database, +}; use atuin_common::api::*; #[instrument(skip_all, fields(user.id = user.id))] pub async fn count( - user: User, + UserAuth(user): UserAuth, state: State>, ) -> Result, ErrorResponseStatus<'static>> { let db = &state.0.database; @@ -42,7 +44,7 @@ pub async fn count( #[instrument(skip_all, fields(user.id = user.id))] pub async fn list( req: Query, - user: User, + UserAuth(user): UserAuth, headers: HeaderMap, state: State>, ) -> Result, ErrorResponseStatus<'static>> { @@ -101,7 +103,7 @@ pub async fn list( #[instrument(skip_all, fields(user.id = user.id))] pub async fn delete( - user: User, + UserAuth(user): UserAuth, state: State>, Json(req): Json, ) -> Result, ErrorResponseStatus<'static>> { @@ -123,13 +125,15 @@ pub async fn delete( #[instrument(skip_all, fields(user.id = user.id))] pub async fn add( - user: User, + UserAuth(user): UserAuth, state: State>, Json(req): Json>, ) -> Result<(), ErrorResponseStatus<'static>> { + let State(AppState { database, settings }) = state; + debug!("request to add {} history items", req.len()); - let history: Vec = req + let mut history: Vec = req .into_iter() .map(|h| NewHistory { client_id: h.id, @@ -140,8 +144,24 @@ pub async fn add( }) .collect(); - let db = &state.0.database; - if let Err(e) = db.add_history(&history).await { + history.retain(|h| { + // keep if within limit, or limit is 0 (unlimited) + let keep = h.data.len() <= settings.max_history_length || settings.max_history_length == 0; + + // Don't return an error here. We want to insert as much of the + // history list as we can, so log the error and continue going. + if !keep { + tracing::warn!( + "history too long, got length {}, max {}", + h.data.len(), + settings.max_history_length + ); + } + + keep + }); + + if let Err(e) = database.add_history(&history).await { error!("failed to add history: {}", e); return Err(ErrorResponse::reply("failed to add history") @@ -155,7 +175,7 @@ pub async fn add( pub async fn calendar( Path(focus): Path, Query(params): Query>, - user: User, + UserAuth(user): UserAuth, state: State>, ) -> Result>, ErrorResponseStatus<'static>> { let focus = focus.as_str(); diff --git a/atuin-server/src/handlers/status.rs b/atuin-server/src/handlers/status.rs index 97c02886..d9b6afaf 100644 --- a/atuin-server/src/handlers/status.rs +++ b/atuin-server/src/handlers/status.rs @@ -3,7 +3,8 @@ use http::StatusCode; use tracing::instrument; use super::{ErrorResponse, ErrorResponseStatus, RespExt}; -use crate::{database::Database, models::User, router::AppState}; +use crate::router::{AppState, UserAuth}; +use atuin_server_database::Database; use atuin_common::api::*; @@ -11,7 +12,7 @@ const VERSION: &str = env!("CARGO_PKG_VERSION"); #[instrument(skip_all, fields(user.id = user.id))] pub async fn status( - user: User, + UserAuth(user): UserAuth, state: State>, ) -> Result, ErrorResponseStatus<'static>> { let db = &state.0.database; diff --git a/atuin-server/src/handlers/user.rs b/atuin-server/src/handlers/user.rs index e67828e4..75081155 100644 --- a/atuin-server/src/handlers/user.rs +++ b/atuin-server/src/handlers/user.rs @@ -16,10 +16,10 @@ use tracing::{debug, error, info, instrument}; use uuid::Uuid; use super::{ErrorResponse, ErrorResponseStatus, RespExt}; -use crate::{ - database::Database, - models::{NewSession, NewUser, User}, - router::AppState, +use crate::router::{AppState, UserAuth}; +use atuin_server_database::{ + models::{NewSession, NewUser}, + Database, DbError, }; use reqwest::header::CONTENT_TYPE; @@ -64,11 +64,11 @@ pub async fn get( let db = &state.0.database; let user = match db.get_user(username.as_ref()).await { Ok(user) => user, - Err(sqlx::Error::RowNotFound) => { + Err(DbError::NotFound) => { debug!("user not found: {}", username); return Err(ErrorResponse::reply("user not found").with_status(StatusCode::NOT_FOUND)); } - Err(err) => { + Err(DbError::Other(err)) => { error!("database error: {}", err); return Err(ErrorResponse::reply("database error") .with_status(StatusCode::INTERNAL_SERVER_ERROR)); @@ -152,7 +152,7 @@ pub async fn register( #[instrument(skip_all, fields(user.id = user.id))] pub async fn delete( - user: User, + UserAuth(user): UserAuth, state: State>, ) -> Result, ErrorResponseStatus<'static>> { debug!("request to delete user {}", user.id); @@ -175,10 +175,10 @@ pub async fn login( let db = &state.0.database; let user = match db.get_user(login.username.borrow()).await { Ok(u) => u, - Err(sqlx::Error::RowNotFound) => { + Err(DbError::NotFound) => { return Err(ErrorResponse::reply("user not found").with_status(StatusCode::NOT_FOUND)); } - Err(e) => { + Err(DbError::Other(e)) => { error!("failed to get user {}: {}", login.username.clone(), e); return Err(ErrorResponse::reply("database error") @@ -188,11 +188,11 @@ pub async fn login( let session = match db.get_user_session(&user).await { Ok(u) => u, - Err(sqlx::Error::RowNotFound) => { + Err(DbError::NotFound) => { debug!("user session not found for user id={}", user.id); return Err(ErrorResponse::reply("user not found").with_status(StatusCode::NOT_FOUND)); } - Err(err) => { + Err(DbError::Other(err)) => { error!("database error for user {}: {}", login.username, err); return Err(ErrorResponse::reply("database error") .with_status(StatusCode::INTERNAL_SERVER_ERROR)); -- cgit v1.3.1