better sync error messages (#1254)

This commit is contained in:
Conrad Ludgate 2023-09-26 14:44:56 +01:00 committed by GitHub
parent fbed2862fd
commit bdba88c11f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 19 deletions

View file

@ -181,9 +181,19 @@ impl<'a> Client<'a> {
let resp = self.client.get(url).send().await?; let resp = self.client.get(url).send().await?;
let status = resp.status();
if status.is_success() {
let history = resp.json::<SyncHistoryResponse>().await?; let history = resp.json::<SyncHistoryResponse>().await?;
Ok(history) Ok(history)
} else if status.is_client_error() {
let error = resp.json::<ErrorResponse>().await?.reason;
bail!("Could not fetch history: {error}.")
} else if status.is_server_error() {
let error = resp.json::<ErrorResponse>().await?.reason;
bail!("There was an error with the atuin sync service: {error}.\nIf the problem persists, contact the host")
} else {
bail!("There was an error with the atuin sync service: Status {status:?}.\nIf the problem persists, contact the host")
}
} }
pub async fn post_history(&self, history: &[AddHistoryRequest]) -> Result<()> { pub async fn post_history(&self, history: &[AddHistoryRequest]) -> Result<()> {

View file

@ -63,10 +63,6 @@ pub async fn list<DB: Database>(
100 100
}; };
let history = db
.list_history(&user, req.sync_ts, req.history_ts, &req.host, page_size)
.await;
if req.sync_ts.unix_timestamp_nanos() < 0 || req.history_ts.unix_timestamp_nanos() < 0 { if req.sync_ts.unix_timestamp_nanos() < 0 || req.history_ts.unix_timestamp_nanos() < 0 {
error!("client asked for history from < epoch 0"); error!("client asked for history from < epoch 0");
return Err( return Err(
@ -75,6 +71,10 @@ pub async fn list<DB: Database>(
); );
} }
let history = db
.list_history(&user, req.sync_ts, req.history_ts, &req.host, page_size)
.await;
if let Err(e) = history { if let Err(e) = history {
error!("failed to load history: {}", e); error!("failed to load history: {}", e);
return Err(ErrorResponse::reply("failed to load history") return Err(ErrorResponse::reply("failed to load history")

View file

@ -1,4 +1,5 @@
use async_trait::async_trait; use async_trait::async_trait;
use atuin_common::api::ErrorResponse;
use axum::{ use axum::{
extract::FromRequestParts, extract::FromRequestParts,
response::IntoResponse, response::IntoResponse,
@ -11,8 +12,11 @@ use tower::ServiceBuilder;
use tower_http::trace::TraceLayer; use tower_http::trace::TraceLayer;
use super::handlers; use super::handlers;
use crate::settings::Settings; use crate::{
use atuin_server_database::{models::User, Database}; handlers::{ErrorResponseStatus, RespExt},
settings::Settings,
};
use atuin_server_database::{models::User, Database, DbError};
pub struct UserAuth(pub User); pub struct UserAuth(pub User);
@ -21,7 +25,7 @@ impl<DB: Send + Sync> FromRequestParts<AppState<DB>> for UserAuth
where where
DB: Database, DB: Database,
{ {
type Rejection = http::StatusCode; type Rejection = ErrorResponseStatus<'static>;
async fn from_request_parts( async fn from_request_parts(
req: &mut Parts, req: &mut Parts,
@ -30,23 +34,39 @@ where
let auth_header = req let auth_header = req
.headers .headers
.get(http::header::AUTHORIZATION) .get(http::header::AUTHORIZATION)
.ok_or(http::StatusCode::FORBIDDEN)?; .ok_or_else(|| {
let auth_header = auth_header ErrorResponse::reply("missing authorization header")
.to_str() .with_status(http::StatusCode::BAD_REQUEST)
.map_err(|_| http::StatusCode::FORBIDDEN)?; })?;
let (typ, token) = auth_header let auth_header = auth_header.to_str().map_err(|_| {
.split_once(' ') ErrorResponse::reply("invalid authorization header encoding")
.ok_or(http::StatusCode::FORBIDDEN)?; .with_status(http::StatusCode::BAD_REQUEST)
})?;
let (typ, token) = auth_header.split_once(' ').ok_or_else(|| {
ErrorResponse::reply("invalid authorization header encoding")
.with_status(http::StatusCode::BAD_REQUEST)
})?;
if typ != "Token" { if typ != "Token" {
return Err(http::StatusCode::FORBIDDEN); return Err(
ErrorResponse::reply("invalid authorization header encoding")
.with_status(http::StatusCode::BAD_REQUEST),
);
} }
let user = state let user = state
.database .database
.get_session_user(token) .get_session_user(token)
.await .await
.map_err(|_| http::StatusCode::FORBIDDEN)?; .map_err(|e| match e {
DbError::NotFound => ErrorResponse::reply("session not found")
.with_status(http::StatusCode::FORBIDDEN),
DbError::Other(e) => {
tracing::error!(error = ?e, "could not query user session");
ErrorResponse::reply("could not query user session")
.with_status(http::StatusCode::INTERNAL_SERVER_ERROR)
}
})?;
Ok(UserAuth(user)) Ok(UserAuth(user))
} }