diff --git a/domain/src/error.rs b/domain/src/error.rs index bb8f675f..9b218a6c 100644 --- a/domain/src/error.rs +++ b/domain/src/error.rs @@ -40,6 +40,7 @@ pub enum InternalErrorKind { pub enum EntityErrorKind { NotFound, Invalid, + Unauthenticated, DbTransaction, Other(String), } @@ -71,6 +72,7 @@ impl From for Error { let entity_error_kind = match err.error_kind { EntityApiErrorKind::RecordNotFound => EntityErrorKind::NotFound, EntityApiErrorKind::InvalidQueryTerm => EntityErrorKind::Invalid, + EntityApiErrorKind::RecordUnauthenticated => EntityErrorKind::Unauthenticated, _ => EntityErrorKind::Other("EntityErrorKind".to_string()), }; diff --git a/web/src/controller/user_session_controller.rs b/web/src/controller/user_session_controller.rs index 6e03f14d..fdf816e2 100644 --- a/web/src/controller/user_session_controller.rs +++ b/web/src/controller/user_session_controller.rs @@ -1,4 +1,5 @@ use crate::controller::ApiResponse; +use crate::error::{Error as WebError, Result as WebResult}; use axum::{http::StatusCode, response::IntoResponse, Form, Json}; use domain::user::{AuthSession, Credentials}; use log::*; @@ -36,17 +37,44 @@ pub struct NextUrl { pub async fn login( mut auth_session: AuthSession, Form(creds): Form, -) -> impl IntoResponse { +) -> WebResult { debug!("UserSessionController::login()"); let user = match auth_session.authenticate(creds.clone()).await { Ok(Some(user)) => user, - Ok(None) => return Err(StatusCode::UNAUTHORIZED.into_response()), - Err(_) => return Err(StatusCode::INTERNAL_SERVER_ERROR.into_response()), + Ok(None) => { + // No user found - this should also be treated as an authentication error + return Err(WebError::from(domain::error::Error { + source: None, + error_kind: domain::error::DomainErrorKind::Internal( + domain::error::InternalErrorKind::Entity( + domain::error::EntityErrorKind::Unauthenticated, + ), + ), + })); + } + Err(auth_error) => { + // axum_login errors contain our entity_api::Error in the error field + warn!("Authentication failed: {:?}", auth_error); + return Err(WebError::from(domain::error::Error { + source: Some(Box::new(auth_error)), + error_kind: domain::error::DomainErrorKind::Internal( + domain::error::InternalErrorKind::Entity( + domain::error::EntityErrorKind::Unauthenticated, + ), + ), + })); + } }; - if auth_session.login(&user).await.is_err() { - return Err(StatusCode::INTERNAL_SERVER_ERROR.into_response()); + if let Err(login_error) = auth_session.login(&user).await { + warn!("Session login failed: {:?}", login_error); + return Err(WebError::from(domain::error::Error { + source: Some(Box::new(login_error)), + error_kind: domain::error::DomainErrorKind::Internal( + domain::error::InternalErrorKind::Other("Session login failed".to_string()), + ), + })); } let user_session_json = json!({ diff --git a/web/src/error.rs b/web/src/error.rs index 829c3d7f..30ea38e2 100644 --- a/web/src/error.rs +++ b/web/src/error.rs @@ -88,6 +88,13 @@ impl Error { ); (StatusCode::NOT_FOUND, "NOT FOUND").into_response() } + EntityErrorKind::Unauthenticated => { + warn!( + "EntityErrorKind::Unauthenticated: Responding with 401 Unauthorized. Error: {:?}", + self + ); + (StatusCode::UNAUTHORIZED, "UNAUTHORIZED").into_response() + } EntityErrorKind::DbTransaction => { warn!( "EntityErrorKind::DbTransaction: Responding with 500 Internal Server Error. Error: {:?}",