From fc710b7afc2f8ff28729ee88315fd74777476c05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Sch=C3=B6nenberg?= Date: Tue, 17 Oct 2023 00:11:47 +0200 Subject: [PATCH] feat(ch-app): Removed ApiResponse, fixed warnings and hid more doc_type related functions --- clearing-house-app/Cargo.toml | 1 + clearing-house-app/src/db/key_store.rs | 8 ++- clearing-house-app/src/errors.rs | 22 ------- clearing-house-app/src/main.rs | 4 +- clearing-house-app/src/model/claims.rs | 59 +----------------- clearing-house-app/src/model/doc_type.rs | 2 + clearing-house-app/src/model/document.rs | 14 ----- clearing-house-app/src/model/ids/message.rs | 46 -------------- clearing-house-app/src/model/ids/mod.rs | 17 ------ clearing-house-app/src/model/ids/request.rs | 15 +---- clearing-house-app/src/model/process.rs | 6 -- clearing-house-app/src/ports/doc_type_api.rs | 42 +++++++------ clearing-house-app/src/ports/logging_api.rs | 40 ++++++------ clearing-house-app/src/ports/mod.rs | 41 +------------ .../src/services/keyring_service.rs | 61 ++++++++++--------- .../src/services/logging_service.rs | 21 +------ 16 files changed, 95 insertions(+), 304 deletions(-) delete mode 100644 clearing-house-app/src/errors.rs diff --git a/clearing-house-app/Cargo.toml b/clearing-house-app/Cargo.toml index 4fe145e..cfaf038 100644 --- a/clearing-house-app/Cargo.toml +++ b/clearing-house-app/Cargo.toml @@ -64,5 +64,6 @@ serial_test = "2.0.0" tempfile = "3.8.0" [features] +default = [] # Enables the doc_type API doc_type = [] diff --git a/clearing-house-app/src/db/key_store.rs b/clearing-house-app/src/db/key_store.rs index d8721c8..ad85931 100644 --- a/clearing-house-app/src/db/key_store.rs +++ b/clearing-house-app/src/db/key_store.rs @@ -2,8 +2,10 @@ use super::DataStoreApi; use crate::db::init_database_client; use crate::model::constants::{ FILE_DEFAULT_DOC_TYPE, KEYRING_DB, KEYRING_DB_CLIENT, MONGO_COLL_DOC_TYPES, - MONGO_COLL_MASTER_KEY, MONGO_ID, MONGO_PID, + MONGO_COLL_MASTER_KEY, MONGO_ID }; +#[cfg(doc_type)] +use crate::model::constants::MONGO_PID; use crate::model::crypto::MasterKey; use crate::model::doc_type::DocumentType; use anyhow::anyhow; @@ -179,6 +181,7 @@ impl KeyStore { } //TODO: Do we need to check that no documents of this type exist before we remove it from the db? + #[cfg(doc_type)] pub async fn delete_document_type(&self, id: &String, pid: &String) -> anyhow::Result { let coll = self .database @@ -194,6 +197,7 @@ impl KeyStore { } /// checks if the model exits + #[cfg(doc_type)] pub async fn exists_document_type(&self, pid: &String, dt_id: &String) -> anyhow::Result { let coll = self .database @@ -214,6 +218,7 @@ impl KeyStore { } } + #[cfg(doc_type)] pub async fn get_all_document_types(&self) -> anyhow::Result> { let coll = self .database @@ -241,6 +246,7 @@ impl KeyStore { } } + #[cfg(doc_type)] pub async fn update_document_type( &self, doc_type: DocumentType, diff --git a/clearing-house-app/src/errors.rs b/clearing-house-app/src/errors.rs deleted file mode 100644 index 5baf5be..0000000 --- a/clearing-house-app/src/errors.rs +++ /dev/null @@ -1,22 +0,0 @@ -type AppResult = Result; - -#[derive(Debug)] -pub enum AppError { - Generic(anyhow::Error), -} - -impl std::error::Error for AppError {} - -impl std::fmt::Display for AppError { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - match self { - AppError::Generic(e) => write!(f, "{}", e), - } - } -} - -impl From for AppError { - fn from(err: anyhow::Error) -> Self { - Self::Generic(err) - } -} diff --git a/clearing-house-app/src/main.rs b/clearing-house-app/src/main.rs index 1f3a4b7..75f5284 100644 --- a/clearing-house-app/src/main.rs +++ b/clearing-house-app/src/main.rs @@ -15,7 +15,6 @@ use std::sync::Arc; mod config; mod crypto; mod db; -mod errors; mod model; mod ports; mod services; @@ -24,6 +23,7 @@ mod util; /// Contains the application state #[derive(Clone)] pub(crate) struct AppState { + #[cfg_attr(not(doc_type), allow(dead_code))] pub keyring_service: Arc, pub logging_service: Arc, pub service_config: Arc, @@ -92,7 +92,7 @@ async fn main() -> Result<(), anyhow::Error> { // Bind port and start server let addr = SocketAddr::from(([0, 0, 0, 0], 8000)); - tracing::info!("Starting server: Listening on {}", addr); + info!("Starting server: Listening on {}", addr); Ok(axum::Server::bind(&addr) .serve(app.into_make_service()) .with_graceful_shutdown(util::shutdown_signal()) diff --git a/clearing-house-app/src/model/claims.rs b/clearing-house-app/src/model/claims.rs index ebb944b..f5b3a07 100644 --- a/clearing-house-app/src/model/claims.rs +++ b/clearing-house-app/src/model/claims.rs @@ -3,7 +3,6 @@ use crate::AppState; use anyhow::Context; use axum::extract::FromRef; use axum::response::IntoResponse; -use chrono::{Duration, Utc}; use num_bigint::BigUint; use ring::signature::KeyPair; use std::env; @@ -27,12 +26,6 @@ impl std::fmt::Display for ChClaims { } } -#[derive(Debug)] -pub enum ChClaimsError { - Missing, - Invalid, -} - pub struct ExtractChClaims(pub ChClaims); #[async_trait::async_trait] @@ -72,7 +65,8 @@ where } pub fn get_jwks(key_path: &str) -> Option> { - let keypair = biscuit::jws::Secret::rsa_keypair_from_file(key_path).unwrap(); + let keypair = biscuit::jws::Secret::rsa_keypair_from_file(key_path) + .unwrap_or_else(|_| panic!("Failed to load keyfile from path {key_path}")); if let biscuit::jws::Secret::RsaKeyPair(a) = keypair { let pk_modulus = BigUint::from_bytes_be( @@ -134,55 +128,6 @@ pub fn get_fingerprint(key_path: &str) -> Option { } } -pub fn create_service_token(issuer: &str, audience: &str, client_id: &str) -> String { - let private_claims = ChClaims::new(client_id); - create_token(issuer, audience, &private_claims) -} - -pub fn create_token< - T: std::fmt::Display + Clone + serde::Serialize + for<'de> serde::Deserialize<'de>, ->( - issuer: &str, - audience: &str, - private_claims: &T, -) -> String { - let signing_secret = match env::var(ENV_SHARED_SECRET) { - Ok(secret) => biscuit::jws::Secret::Bytes(secret.to_string().into_bytes()), - Err(_) => { - panic!( - "Shared Secret not configured. Please configure environment variable {}", - ENV_SHARED_SECRET - ); - } - }; - let expiration_date = Utc::now() + Duration::minutes(5); - - let claims = biscuit::ClaimsSet:: { - registered: biscuit::RegisteredClaims { - issuer: Some(issuer.to_string()), - issued_at: Some(biscuit::Timestamp::from(Utc::now())), - audience: Some(biscuit::SingleOrMultiple::Single(audience.to_string())), - expiry: Some(biscuit::Timestamp::from(expiration_date)), - ..Default::default() - }, - private: private_claims.clone(), - }; - - // Construct the JWT - let jwt = biscuit::jws::Compact::new_decoded( - From::from(biscuit::jws::RegisteredHeader { - algorithm: biscuit::jwa::SignatureAlgorithm::HS256, - ..Default::default() - }), - claims, - ); - - jwt.into_encoded(&signing_secret) - .unwrap() - .unwrap_encoded() - .to_string() -} - pub fn decode_token serde::Deserialize<'de>>( token: &str, audience: &str, diff --git a/clearing-house-app/src/model/doc_type.rs b/clearing-house-app/src/model/doc_type.rs index 2cff304..af9235b 100644 --- a/clearing-house-app/src/model/doc_type.rs +++ b/clearing-house-app/src/model/doc_type.rs @@ -6,6 +6,7 @@ pub struct DocumentType { } impl DocumentType { + #[cfg(test)] pub fn new(id: String, pid: String, parts: Vec) -> DocumentType { DocumentType { id, pid, parts } } @@ -17,6 +18,7 @@ pub struct DocumentTypePart { } impl DocumentTypePart { + #[cfg(test)] pub fn new(name: String) -> DocumentTypePart { DocumentTypePart { name } } diff --git a/clearing-house-app/src/model/document.rs b/clearing-house-app/src/model/document.rs index da6219c..5104db7 100644 --- a/clearing-house-app/src/model/document.rs +++ b/clearing-house-app/src/model/document.rs @@ -277,20 +277,6 @@ impl EncryptedDocument { } } -/// companion to format_pt_for_storage -pub fn restore_pt(pt: &str) -> anyhow::Result<(String, String, String)> { - trace!("Trying to restore plain text"); - let vec: Vec<&str> = pt.split(SPLIT_CT).collect(); - if vec.len() != 3 { - anyhow::bail!("Could not restore plaintext"); - } - Ok(( - String::from(vec[0]), - String::from(vec[1]), - String::from(vec[2]), - )) -} - /// companion to format_pt_for_storage_no_dt pub fn restore_pt_no_dt(pt: &str) -> anyhow::Result<(String, String)> { trace!("Trying to restore plain text"); diff --git a/clearing-house-app/src/model/ids/message.rs b/clearing-house-app/src/model/ids/message.rs index a089797..b5c6970 100644 --- a/clearing-house-app/src/model/ids/message.rs +++ b/clearing-house-app/src/model/ids/message.rs @@ -16,10 +16,6 @@ const SENDER_AGENT: &str = "sender_agent"; const PAYLOAD: &str = "payload"; const PAYLOAD_TYPE: &str = "payload_type"; -pub const RESULT_MESSAGE: &str = "ResultMessage"; -pub const REJECTION_MESSAGE: &str = "RejectionMessage"; -pub const MESSAGE_PROC_NOTIFICATION_MESSAGE: &str = "MessageProcessedNotificationMessage"; - /// Metadata describing payload exchanged by interacting Connectors. #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct IdsMessage { @@ -143,48 +139,6 @@ impl Default for IdsMessage { } impl IdsMessage { - pub fn processed(msg: IdsMessage) -> IdsMessage { - let mut message = IdsMessage::clone(msg); - message.id = Some(autogen(MESSAGE_PROC_NOTIFICATION_MESSAGE)); - message.type_message = MessageType::MessageProcessedNotificationMessage; - message - } - - pub fn return_result(msg: IdsMessage) -> IdsMessage { - let mut message = IdsMessage::clone(msg); - message.id = Some(autogen(RESULT_MESSAGE)); - message.type_message = MessageType::ResultMessage; - message - } - - pub fn error(msg: IdsMessage) -> IdsMessage { - let mut message = IdsMessage::clone(msg); - message.id = Some(autogen(REJECTION_MESSAGE)); - message.type_message = MessageType::RejectionMessage; - message - } - - fn clone(msg: IdsMessage) -> IdsMessage { - IdsMessage { - context: msg.context.clone(), - type_message: msg.type_message.clone(), - id: msg.id.clone(), - pid: msg.pid.clone(), - model_version: msg.model_version.clone(), - correlation_message: msg.correlation_message.clone(), - issued: msg.issued.clone(), - issuer_connector: msg.issuer_connector.clone(), - sender_agent: msg.sender_agent.clone(), - recipient_connector: msg.recipient_connector.clone(), - recipient_agent: msg.recipient_agent.clone(), - transfer_contract: msg.transfer_contract.clone(), - security_token: msg.security_token.clone(), - authorization_token: msg.authorization_token.clone(), - payload: msg.payload.clone(), - content_version: msg.content_version.clone(), - payload_type: msg.payload.clone(), - } - } pub fn restore() -> IdsMessage { IdsMessage { diff --git a/clearing-house-app/src/model/ids/mod.rs b/clearing-house-app/src/model/ids/mod.rs index d6fa87c..ad494b3 100644 --- a/clearing-house-app/src/model/ids/mod.rs +++ b/clearing-house-app/src/model/ids/mod.rs @@ -42,9 +42,6 @@ impl InfoModelId { pub fn new(id: String) -> InfoModelId { InfoModelId::SimpleId(id) } - pub fn complex(id: InfoModelComplexId) -> InfoModelId { - InfoModelId::ComplexId(id) - } } impl std::fmt::Display for InfoModelId { @@ -73,9 +70,6 @@ impl InfoModelDateTime { pub fn new() -> InfoModelDateTime { InfoModelDateTime::Time(chrono::Local::now()) } - pub fn complex() -> InfoModelDateTime { - InfoModelDateTime::ComplexTime(InfoModelTimeStamp::default()) - } } impl std::fmt::Display for InfoModelDateTime { @@ -346,17 +340,6 @@ pub struct SecurityToken { pub token_value: String, } -impl SecurityToken { - pub fn new() -> SecurityToken { - SecurityToken { - type_message: MessageType::DAPSToken, - id: Some(String::new()), - token_format: None, - token_value: String::new(), - } - } -} - #[derive(Clone, serde::Serialize, serde::Deserialize, Debug)] pub struct IdsQueryResult { pub date_from: String, diff --git a/clearing-house-app/src/model/ids/request.rs b/clearing-house-app/src/model/ids/request.rs index fac3d7f..88fa8cf 100644 --- a/clearing-house-app/src/model/ids/request.rs +++ b/clearing-house-app/src/model/ids/request.rs @@ -1,5 +1,6 @@ use crate::model::ids::message::IdsMessage; +/// IDS Multipart message represented as a JSON struct #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct ClearingHouseMessage { pub header: IdsMessage, @@ -7,17 +8,3 @@ pub struct ClearingHouseMessage { #[serde(rename = "payloadType")] pub payload_type: Option, } - -impl ClearingHouseMessage { - pub fn new( - header: IdsMessage, - payload: Option, - payload_type: Option, - ) -> ClearingHouseMessage { - ClearingHouseMessage { - header, - payload, - payload_type, - } - } -} diff --git a/clearing-house-app/src/model/process.rs b/clearing-house-app/src/model/process.rs index c623f90..d2f095c 100644 --- a/clearing-house-app/src/model/process.rs +++ b/clearing-house-app/src/model/process.rs @@ -24,12 +24,6 @@ pub struct OwnerList { pub owners: Vec, } -impl OwnerList { - pub fn new(owners: Vec) -> Self { - Self { owners } - } -} - #[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)] pub struct Receipt { pub data: biscuit::jws::Compact, diff --git a/clearing-house-app/src/ports/doc_type_api.rs b/clearing-house-app/src/ports/doc_type_api.rs index ac404f9..eb4df3e 100644 --- a/clearing-house-app/src/ports/doc_type_api.rs +++ b/clearing-house-app/src/ports/doc_type_api.rs @@ -1,17 +1,21 @@ +use axum::http::StatusCode; use crate::model::constants::DEFAULT_PROCESS_ID; use crate::ports::ApiResponse; use crate::model::doc_type::DocumentType; +use crate::services::keyring_service::KeyringServiceError; + +type DocApiResult = super::ApiResult; async fn create_doc_type( axum::extract::State(state): axum::extract::State, axum::extract::Json(doc_type): axum::extract::Json, -) -> ApiResponse { +) -> DocApiResult { match state.keyring_service.create_doc_type(doc_type).await { - Ok(dt) => ApiResponse::SuccessCreate(dt), + Ok(dt) => Ok((StatusCode::CREATED, Json(dt))), Err(e) => { error!("Error while adding doctype: {:?}", e); - ApiResponse::InternalError(e.to_string()) + Err(e) } } } @@ -20,12 +24,12 @@ async fn update_doc_type( axum::extract::State(state): axum::extract::State, axum::extract::Path(id): axum::extract::Path, axum::extract::Json(doc_type): axum::extract::Json, -) -> ApiResponse { +) -> DocApiResult { match state.keyring_service.update_doc_type(id, doc_type).await { - Ok(id) => ApiResponse::SuccessOk(id), + Ok(id) => Ok((StatusCode::OK, Json(id))), Err(e) => { error!("Error while adding doctype: {:?}", e); - ApiResponse::InternalError(e.to_string()) + Err(e) } } } @@ -33,7 +37,7 @@ async fn update_doc_type( async fn delete_default_doc_type( state: axum::extract::State, id: axum::extract::Path, -) -> ApiResponse { +) -> DocApiResult { delete_doc_type( state, id, @@ -46,12 +50,12 @@ async fn delete_doc_type( axum::extract::State(state): axum::extract::State, axum::extract::Path(id): axum::extract::Path, axum::extract::Path(pid): axum::extract::Path, -) -> ApiResponse { +) -> DocApiResult { match state.keyring_service.delete_doc_type(id, pid).await { - Ok(id) => ApiResponse::SuccessOk(id), + Ok(id) => Ok((StatusCode::OK, Json(id))), Err(e) => { error!("Error while deleting doctype: {:?}", e); - ApiResponse::InternalError(e.to_string()) + Err(e) } } } @@ -59,7 +63,7 @@ async fn delete_doc_type( async fn get_default_doc_type( state: axum::extract::State, id: axum::extract::Path, -) -> ApiResponse> { +) -> DocApiResult> { get_doc_type( state, id, @@ -73,15 +77,15 @@ async fn get_doc_type( axum::extract::State(state): axum::extract::State, axum::extract::Path(id): axum::extract::Path, axum::extract::Path(pid): axum::extract::Path, -) -> ApiResponse> { +) -> DocApiResult> { match state.keyring_service.get_doc_type(id, pid).await { Ok(dt) => match dt { - Some(dt) => ApiResponse::SuccessOk(Some(dt)), - None => ApiResponse::SuccessOk(None), + Some(dt) => Ok((StatusCode::OK, Json(Some(dt)))), + None => Ok((StatusCode::OK, Json(None))) }, Err(e) => { error!("Error while retrieving doctype: {:?}", e); - ApiResponse::InternalError(e.to_string()) + Err(e) } } } @@ -89,12 +93,12 @@ async fn get_doc_type( //#[rocket::get("/", format = "json")] async fn get_doc_types( axum::extract::State(state): axum::extract::State, -) -> ApiResponse> { +) -> DocApiResult> { match state.keyring_service.get_doc_types().await { - Ok(dt) => ApiResponse::SuccessOk(dt), + Ok(dt) => Ok((StatusCode::OK, Json(dt))), Err(e) => { - error!("Error while retrieving doctypes: {:?}", e); - ApiResponse::InternalError(e.to_string()) + error!("Error while retrieving doc_types: {:?}", e); + Err(e) } } } diff --git a/clearing-house-app/src/ports/logging_api.rs b/clearing-house-app/src/ports/logging_api.rs index 58a0ba0..4060d31 100644 --- a/clearing-house-app/src/ports/logging_api.rs +++ b/clearing-house-app/src/ports/logging_api.rs @@ -1,27 +1,32 @@ +use axum::http::StatusCode; +use axum::Json; use crate::model::claims::ExtractChClaims; -use crate::{model::claims::get_jwks, model::SortingOrder, ports::ApiResponse, AppState}; +use crate::{model::claims::get_jwks, model::SortingOrder, AppState}; use biscuit::jwk::JWKSet; use crate::model::ids::message::IdsMessage; use crate::model::ids::request::ClearingHouseMessage; use crate::model::ids::IdsQueryResult; use crate::model::process::Receipt; +use crate::services::logging_service::LoggingServiceError; + +type LoggingApiResult = super::ApiResult; async fn log( ExtractChClaims(ch_claims): ExtractChClaims, axum::extract::State(state): axum::extract::State, axum::extract::Path(pid): axum::extract::Path, axum::extract::Json(message): axum::extract::Json, -) -> ApiResponse { +) -> LoggingApiResult { match state .logging_service .log(ch_claims, state.signing_key_path.as_str(), message, pid) .await { - Ok(id) => ApiResponse::SuccessCreate(id), + Ok(id) => Ok((StatusCode::CREATED, Json(id))), Err(e) => { error!("Error while logging: {:?}", e); - ApiResponse::InternalError(String::from("Error while logging!")) + Err(e) } } } @@ -31,16 +36,16 @@ async fn create_process( axum::extract::State(state): axum::extract::State, axum::extract::Path(pid): axum::extract::Path, axum::extract::Json(message): axum::extract::Json, -) -> ApiResponse { +) -> LoggingApiResult { match state .logging_service .create_process(ch_claims, message, pid) .await { - Ok(id) => ApiResponse::SuccessCreate(id), + Ok(id) => Ok((StatusCode::CREATED, Json(id))), Err(e) => { error!("Error while creating process: {:?}", e); - ApiResponse::InternalError(String::from("Error while creating process!")) + Err(e) } } } @@ -59,8 +64,8 @@ async fn query_pid( axum::extract::State(state): axum::extract::State, axum::extract::Query(params): axum::extract::Query, axum::extract::Path(pid): axum::extract::Path, - axum::extract::Json(message): axum::extract::Json, -) -> ApiResponse { + axum::extract::Json(_): axum::extract::Json, +) -> LoggingApiResult { match state .logging_service .query_pid( @@ -71,14 +76,13 @@ async fn query_pid( params.date_to, params.date_from, pid, - message, ) .await { - Ok(result) => ApiResponse::SuccessOk(result), + Ok(result) => Ok((StatusCode::OK, Json(result))), Err(e) => { error!("Error while querying: {:?}", e); - ApiResponse::InternalError(String::from("Error while querying!")) + Err(e) } } } @@ -89,26 +93,26 @@ async fn query_id( axum::extract::Path(pid): axum::extract::Path, axum::extract::Path(id): axum::extract::Path, axum::extract::Json(message): axum::extract::Json, -) -> ApiResponse { +) -> LoggingApiResult { match state .logging_service .query_id(ch_claims, pid, id, message) .await { - Ok(result) => ApiResponse::SuccessOk(result), + Ok(result) => Ok((StatusCode::OK, Json(result))), Err(e) => { error!("Error while querying: {:?}", e); - ApiResponse::InternalError(String::from("Error while querying!")) + Err(e) } } } async fn get_public_sign_key( axum::extract::State(state): axum::extract::State, -) -> ApiResponse> { +) -> super::ApiResult, &'static str> { match get_jwks(state.signing_key_path.as_str()) { - Some(jwks) => ApiResponse::SuccessOk(jwks), - None => ApiResponse::InternalError(String::from("Error reading signing key")), + Some(jwks) => Ok((StatusCode::OK, Json(jwks))), + None => Err("Error reading signing key"), } } diff --git a/clearing-house-app/src/ports/mod.rs b/clearing-house-app/src/ports/mod.rs index 3322d40..3636fbb 100644 --- a/clearing-house-app/src/ports/mod.rs +++ b/clearing-house-app/src/ports/mod.rs @@ -3,7 +3,6 @@ //! This module contains the ports of the logging service. Ports are used to communicate with other //! services. In this case, the logging service implements REST-API endpoints to provide access to //! the logging service. -use axum::response::Response; use crate::AppState; #[cfg(doc_type)] @@ -25,41 +24,5 @@ pub(crate) fn router() -> axum::routing::Router { .merge(logging_api::router()) } -#[derive(Debug)] -pub(crate) enum ApiResponse { - PreFlight(()), - BadRequest(String), - SuccessCreate(T), - SuccessOk(T), - SuccessNoContent(String), - Unauthorized(String), - Forbidden(String), - NotFound(String), - InternalError(String), -} - -impl axum::response::IntoResponse for ApiResponse { - fn into_response(self) -> Response { - match self { - ApiResponse::PreFlight(_) => (axum::http::StatusCode::OK, "").into_response(), - ApiResponse::BadRequest(s) => (axum::http::StatusCode::BAD_REQUEST, s).into_response(), - ApiResponse::SuccessCreate(v) => { - (axum::http::StatusCode::CREATED, axum::response::Json(v)).into_response() - } - ApiResponse::SuccessOk(v) => { - (axum::http::StatusCode::OK, axum::response::Json(v)).into_response() - } - ApiResponse::SuccessNoContent(s) => { - (axum::http::StatusCode::NO_CONTENT, s).into_response() - } - ApiResponse::Unauthorized(s) => { - (axum::http::StatusCode::UNAUTHORIZED, s).into_response() - } - ApiResponse::Forbidden(s) => (axum::http::StatusCode::FORBIDDEN, s).into_response(), - ApiResponse::NotFound(s) => (axum::http::StatusCode::NOT_FOUND, s).into_response(), - ApiResponse::InternalError(s) => { - (axum::http::StatusCode::INTERNAL_SERVER_ERROR, s).into_response() - } - } - } -} +/// Result type alias for the API +pub(crate) type ApiResult = Result<(axum::http::StatusCode, axum::response::Json), E>; \ No newline at end of file diff --git a/clearing-house-app/src/services/keyring_service.rs b/clearing-house-app/src/services/keyring_service.rs index 2cbd6a2..df08149 100644 --- a/clearing-house-app/src/services/keyring_service.rs +++ b/clearing-house-app/src/services/keyring_service.rs @@ -19,6 +19,9 @@ pub enum KeyringServiceError { }, #[error("Error while decrypting keys")] DecryptionError, + #[cfg_attr(not(doc_type), allow(dead_code))] + #[error("Document type already exists")] + DocumentTypeAlreadyExists, } impl axum::response::IntoResponse for KeyringServiceError { @@ -31,6 +34,7 @@ impl axum::response::IntoResponse for KeyringServiceError { Self::DatabaseError { source, description } => (StatusCode::INTERNAL_SERVER_ERROR, format!("{}: {}", description, source)).into_response(), Self::DecryptionError => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()).into_response(), + Self::DocumentTypeAlreadyExists => (StatusCode::BAD_REQUEST, self.to_string()).into_response(), } } } @@ -77,13 +81,13 @@ impl KeyringService { } Err(e) => { warn!("Error while retrieving document type: {}", e); - Err(KeyringServiceError::DatabaseError {source: e, description: "Error while retrieving document type".to_string()}) + Err(KeyringServiceError::DatabaseError { source: e, description: "Error while retrieving document type".to_string() }) } } } Err(e) => { error!("Error while retrieving master key: {}", e); - Err(KeyringServiceError::DatabaseError {source: e, description: "Error while retrieving master key".to_string()}) + Err(KeyringServiceError::DatabaseError { source: e, description: "Error while retrieving master key".to_string() }) } } } @@ -146,7 +150,7 @@ impl KeyringService { } Err(e) => { warn!("Error while retrieving document type: {}", e); - Err(KeyringServiceError::DatabaseError {source: e, description: "Error while retrieving document type".to_string()}) + Err(KeyringServiceError::DatabaseError { source: e, description: "Error while retrieving document type".to_string() }) } } } @@ -194,7 +198,7 @@ impl KeyringService { } Err(e) => { warn!("Error while retrieving document type: {}", e); - Err(KeyringServiceError::DatabaseError {source: e, description: "Error while retrieving document type".to_string()}) + Err(KeyringServiceError::DatabaseError { source: e, description: "Error while retrieving document type".to_string() }) } } } @@ -218,27 +222,27 @@ impl KeyringService { #[cfg(doc_type)] pub(crate) async fn create_doc_type( &self, - doc_type: DocumentType, - ) -> anyhow::Result { + doc_type: crate::model::doc_type::DocumentType, + ) -> Result { debug!("adding doctype: {:?}", &doc_type); match self .db .exists_document_type(&doc_type.pid, &doc_type.id) .await { - Ok(true) => Err(anyhow!("doctype already exists!")), // BadRequest + Ok(true) => Err(KeyringServiceError::DocumentTypeAlreadyExists), // BadRequest Ok(false) => { match self.db.add_document_type(doc_type.clone()).await { Ok(()) => Ok(doc_type), Err(e) => { error!("Error while adding doctype: {:?}", e); - Err(anyhow!("Error while adding document type!")) // InternalError + Err(KeyringServiceError::DatabaseError { source: e, description: "Error while adding doctype".to_string() }) } } } Err(e) => { error!("Error while adding document type: {:?}", e); - Err(anyhow!("Error while checking database!")) // InternalError + Err(KeyringServiceError::DatabaseError { source: e, description: "Error while checking doctype".to_string() }) } } } @@ -247,41 +251,42 @@ impl KeyringService { pub(crate) async fn update_doc_type( &self, id: String, - doc_type: DocumentType, - ) -> anyhow::Result { + doc_type: crate::model::doc_type::DocumentType, + ) -> Result { match self .db .exists_document_type(&doc_type.pid, &doc_type.id) .await { - Ok(true) => Err(anyhow!("Doctype already exists!")), // BadRequest + Ok(true) => Err(KeyringServiceError::DocumentTypeAlreadyExists), Ok(false) => { match self.db.update_document_type(doc_type, &id).await { Ok(id) => Ok(id), Err(e) => { error!("Error while adding doctype: {:?}", e); - Err(anyhow!("Error while storing document type!")) // InternalError + Err(KeyringServiceError::DatabaseError { source: e, description: "Error while storing document type!".to_string() }) } } } Err(e) => { error!("Error while adding document type: {:?}", e); - Err(anyhow!("Error while checking database!")) // InternalError + Err(KeyringServiceError::DatabaseError { source: e, description: "Error while checking doctype".to_string() }) } } } #[cfg(doc_type)] - pub(crate) async fn delete_doc_type(&self, id: String, pid: String) -> anyhow::Result { + pub(crate) async fn delete_doc_type(&self, id: String, pid: String) -> Result { match self.db.delete_document_type(&id, &pid).await { Ok(true) => Ok(String::from("Document type deleted!")), // NoContent - Ok(false) => Err(anyhow!("Document type does not exist!")), // NotFound + Ok(false) => Err(KeyringServiceError::DocumentTypeNotFound), Err(e) => { error!("Error while deleting doctype: {:?}", e); - Err(anyhow!( - "Error while deleting document type with id {}!", - id - )) // InternalError + Err(KeyringServiceError::DatabaseError { + source: e, + description: format!("Error while deleting document type with id {}!", + id), + }) } } } @@ -291,30 +296,28 @@ impl KeyringService { &self, id: String, pid: String, - ) -> anyhow::Result> { + ) -> Result, KeyringServiceError> { match self.db.get_document_type(&id).await { //TODO: would like to send "{}" instead of "null" when dt is not found Ok(dt) => Ok(dt), Err(e) => { error!("Error while retrieving doctype: {:?}", e); - Err(anyhow!( - "Error while retrieving document type with id {} and pid {}!", - id, - pid - )) // InternalError + Err(KeyringServiceError::DatabaseError { source: e, description: format!("Error while retrieving document type with id {} and pid {}!", id, pid) }) } } } #[cfg(doc_type)] - - pub(crate) async fn get_doc_types(&self) -> anyhow::Result> { + pub(crate) async fn get_doc_types(&self) -> Result, KeyringServiceError> { match self.db.get_all_document_types().await { //TODO: would like to send "{}" instead of "null" when dt is not found Ok(dt) => Ok(dt), Err(e) => { error!("Error while retrieving default doc_types: {:?}", e); - Err(anyhow!("Error while retrieving all document types")) // InternalError + Err(KeyringServiceError::DatabaseError { + source: e, + description: "Error while retrieving all document types".to_string(), + }) } } } diff --git a/clearing-house-app/src/services/logging_service.rs b/clearing-house-app/src/services/logging_service.rs index d1ddf96..26010c3 100644 --- a/clearing-house-app/src/services/logging_service.rs +++ b/clearing-house-app/src/services/logging_service.rs @@ -26,13 +26,6 @@ pub enum LoggingServiceError { }, #[error("User not authorized!")] UserNotAuthorized, - #[error("Authorization failed!")] - AuthorizationFailed { - source: anyhow::Error, - description: String, - }, - #[error("Document already exists!")] - DocumentAlreadyExists, #[error("Invalid request received!")] InvalidRequest, #[error("Process already exists!")] @@ -66,17 +59,6 @@ impl axum::response::IntoResponse for LoggingServiceError { Self::UserNotAuthorized => { (StatusCode::FORBIDDEN, self.to_string()).into_response() } - Self::AuthorizationFailed { - source, - description, - } => ( - StatusCode::INTERNAL_SERVER_ERROR, - format!("{}: {}", description, source), - ) - .into_response(), - Self::DocumentAlreadyExists => { - (StatusCode::BAD_REQUEST, self.to_string()).into_response() - } Self::InvalidRequest => { (StatusCode::BAD_REQUEST, self.to_string()).into_response() } @@ -238,7 +220,7 @@ impl LoggingService { match m.payload { Some(ref payload) if !payload.is_empty() => { trace!("OwnerList: '{:#?}'", &payload); - match serde_json::from_str::(&payload) { + match serde_json::from_str::(payload) { Ok(owner_list) => { for o in owner_list.owners { if !owners.contains(&o) { @@ -300,7 +282,6 @@ impl LoggingService { date_to: Option, date_from: Option, pid: String, - _message: ClearingHouseMessage, ) -> Result { debug!("page: {:#?}, size:{:#?} and sort:{:#?}", page, size, sort);