From 5725f4b40b1c612d2059789cb95222ff3b0bf510 Mon Sep 17 00:00:00 2001
From: Conrad Ludgate <conradludgate@gmail.com>
Date: Sat, 8 Oct 2022 04:33:07 +0100
Subject: [PATCH] add some error messages (#510)

* add some error messages

* fmt
---
 atuin-client/src/api_client.rs       |  8 +++++---
 atuin-common/src/api.rs              |  6 ++++++
 atuin-server/src/handlers/history.rs |  2 +-
 atuin-server/src/handlers/mod.rs     | 19 +++++++++----------
 atuin-server/src/handlers/user.rs    |  2 +-
 5 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/atuin-client/src/api_client.rs b/atuin-client/src/api_client.rs
index d0511f8..5692fea 100644
--- a/atuin-client/src/api_client.rs
+++ b/atuin-client/src/api_client.rs
@@ -9,7 +9,7 @@ use reqwest::{
 use sodiumoxide::crypto::secretbox;
 
 use atuin_common::api::{
-    AddHistoryRequest, CountResponse, LoginRequest, LoginResponse, RegisterResponse,
+    AddHistoryRequest, CountResponse, ErrorResponse, LoginRequest, LoginResponse, RegisterResponse,
     SyncHistoryResponse,
 };
 
@@ -58,7 +58,8 @@ pub async fn register(
         .await?;
 
     if !resp.status().is_success() {
-        bail!("failed to register user");
+        let error = resp.json::<ErrorResponse>().await?;
+        bail!("failed to register user: {}", error.reason);
     }
 
     let session = resp.json::<RegisterResponse>().await?;
@@ -77,7 +78,8 @@ pub async fn login(address: &str, req: LoginRequest) -> Result<LoginResponse> {
         .await?;
 
     if resp.status() != reqwest::StatusCode::OK {
-        bail!("invalid login details");
+        let error = resp.json::<ErrorResponse>().await?;
+        bail!("invalid login details: {}", error.reason);
     }
 
     let session = resp.json::<LoginResponse>().await?;
diff --git a/atuin-common/src/api.rs b/atuin-common/src/api.rs
index 47bbcde..ba04fd7 100644
--- a/atuin-common/src/api.rs
+++ b/atuin-common/src/api.rs
@@ -1,5 +1,6 @@
 use chrono::Utc;
 use serde::{Deserialize, Serialize};
+use std::borrow::Cow;
 
 #[derive(Debug, Serialize, Deserialize)]
 pub struct UserResponse {
@@ -53,3 +54,8 @@ pub struct SyncHistoryRequest {
 pub struct SyncHistoryResponse {
     pub history: Vec<String>,
 }
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct ErrorResponse<'a> {
+    pub reason: Cow<'a, str>,
+}
diff --git a/atuin-server/src/handlers/history.rs b/atuin-server/src/handlers/history.rs
index 2b10790..d2fda77 100644
--- a/atuin-server/src/handlers/history.rs
+++ b/atuin-server/src/handlers/history.rs
@@ -7,7 +7,7 @@ use axum::{
 use http::StatusCode;
 use tracing::{debug, error, instrument};
 
-use super::{ErrorResponse, ErrorResponseStatus};
+use super::{ErrorResponse, ErrorResponseStatus, RespExt};
 use crate::{
     calendar::{TimePeriod, TimePeriodInfo},
     database::{Database, Postgres},
diff --git a/atuin-server/src/handlers/mod.rs b/atuin-server/src/handlers/mod.rs
index 4aa7423..4be3e38 100644
--- a/atuin-server/src/handlers/mod.rs
+++ b/atuin-server/src/handlers/mod.rs
@@ -1,5 +1,4 @@
-use std::borrow::Cow;
-
+use atuin_common::api::ErrorResponse;
 use axum::{response::IntoResponse, Json};
 use serde::{Deserialize, Serialize};
 
@@ -23,11 +22,6 @@ pub async fn index() -> Json<IndexResponse> {
     })
 }
 
-#[derive(Debug, Serialize, Deserialize)]
-pub struct ErrorResponse<'a> {
-    pub reason: Cow<'a, str>,
-}
-
 impl<'a> IntoResponse for ErrorResponseStatus<'a> {
     fn into_response(self) -> axum::response::Response {
         (self.status, Json(self.error)).into_response()
@@ -39,15 +33,20 @@ pub struct ErrorResponseStatus<'a> {
     pub status: http::StatusCode,
 }
 
-impl<'a> ErrorResponse<'a> {
-    pub fn with_status(self, status: http::StatusCode) -> ErrorResponseStatus<'a> {
+pub trait RespExt<'a> {
+    fn with_status(self, status: http::StatusCode) -> ErrorResponseStatus<'a>;
+    fn reply(reason: &'a str) -> Self;
+}
+
+impl<'a> RespExt<'a> for ErrorResponse<'a> {
+    fn with_status(self, status: http::StatusCode) -> ErrorResponseStatus<'a> {
         ErrorResponseStatus {
             error: self,
             status,
         }
     }
 
-    pub fn reply(reason: &'a str) -> ErrorResponse {
+    fn reply(reason: &'a str) -> ErrorResponse {
         Self {
             reason: reason.into(),
         }
diff --git a/atuin-server/src/handlers/user.rs b/atuin-server/src/handlers/user.rs
index 42e2b5c..1bc9178 100644
--- a/atuin-server/src/handlers/user.rs
+++ b/atuin-server/src/handlers/user.rs
@@ -6,7 +6,7 @@ use sodiumoxide::crypto::pwhash::argon2id13;
 use tracing::{debug, error, instrument};
 use uuid::Uuid;
 
-use super::{ErrorResponse, ErrorResponseStatus};
+use super::{ErrorResponse, ErrorResponseStatus, RespExt};
 use crate::{
     database::{Database, Postgres},
     models::{NewSession, NewUser},