From bfec3aaaf837cc5bb80a534804966b861c57f897 Mon Sep 17 00:00:00 2001 From: Xu_Mj <40650924+Xu-Mj@users.noreply.github.com> Date: Sun, 28 Jul 2024 09:47:08 +0800 Subject: [PATCH 1/7] feat: rebuild error --- abi/Cargo.toml | 1 + abi/src/config.rs | 4 +- abi/src/errors/mod.rs | 848 +++++++++++++----- abi/src/types/msg.rs | 72 +- api/src/api_utils/custom_extract/auth.rs | 105 +-- .../custom_extract/json_extractor.rs | 25 +- .../custom_extract/path_extractor.rs | 69 +- api/src/handlers/files/file.rs | 22 +- api/src/handlers/friends/friend_handlers.rs | 63 +- api/src/handlers/groups/group_handlers.rs | 110 +-- api/src/handlers/messages/msg_handlers.rs | 14 +- api/src/handlers/users/mod.rs | 37 +- api/src/handlers/users/oauth2.rs | 22 +- api/src/handlers/users/user_handlers.rs | 83 +- consumer/src/lib.rs | 67 +- db/src/database/mongodb/message.rs | 32 +- db/src/database/postgres/group.rs | 4 +- db/src/database/postgres/user.rs | 5 +- db/src/rpc/mod.rs | 6 +- oss/src/client.rs | 36 +- utils/src/lib.rs | 23 +- .../tonic_service_discovery.rs | 5 +- .../src/service_register_center/consul/mod.rs | 4 +- ws/src/manager.rs | 5 +- ws/src/ws_server.rs | 2 +- 25 files changed, 980 insertions(+), 684 deletions(-) diff --git a/abi/Cargo.toml b/abi/Cargo.toml index 4897299..8a69f2e 100644 --- a/abi/Cargo.toml +++ b/abi/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] +aws-sdk-s3 = { version = "1.4.0", features = ["rt-tokio"] } axum = "0.7.4" bincode = "1.3.3" bytes = "1" diff --git a/abi/src/config.rs b/abi/src/config.rs index 8e81d11..b45c2f1 100644 --- a/abi/src/config.rs +++ b/abi/src/config.rs @@ -292,8 +292,8 @@ pub struct OAuth2Item { impl Config { pub fn load(filename: impl AsRef) -> Result { - let content = fs::read_to_string(filename).map_err(|_| Error::ConfigReadError)?; - serde_yaml::from_str(&content).map_err(Error::ConfigParseError) + let content = fs::read_to_string(filename)?; + Ok(serde_yaml::from_str(&content)?) } } diff --git a/abi/src/errors/mod.rs b/abi/src/errors/mod.rs index a79b50f..4e0eaf0 100644 --- a/abi/src/errors/mod.rs +++ b/abi/src/errors/mod.rs @@ -1,283 +1,719 @@ -use axum::http::StatusCode; -use axum::response::{IntoResponse, Response}; -use axum::Json; +// use axum::http::StatusCode; +// use axum::response::{IntoResponse, Response}; +// use axum::Json; +// use mongodb::bson::document::ValueAccessError; +// use serde_json::json; +// use tonic::{Code, Status}; +// use tracing::error; + +// type Message = String; +// type Location = String; +// type Path = String; + +// pub struct Error +// where +// T: std::error::Error, +// { +// kind: ErrorKind, +// error: Option, +// details: Option, +// } + +// #[derive(Debug)] +// pub enum ErrorKind { +// // #[error("unknown errors")] +// UnknownError, + +// // #[error("database errors{0}")] +// DbError/* (sqlx::Error) */, + +// // #[error("config file read errors")] +// ConfigReadError, + +// // #[error("config parse errors")] +// ConfigParseError/* (serde_yaml::Error) */, + +// #[error("Not found by the given condition")] +// NotFound, + +// #[error("broadcast errors")] +// BroadCastError, + +// // 500 +// #[error("internal server errors")] +// InternalServer(Message), + +// // 400 +// #[error("body parsing errors")] +// BodyParsing(Message, Path), + +// #[error("path parsing errors{0}")] +// PathParsing(Message, Option), + +// #[error("unauthorized request{0}, path: {1}")] +// UnAuthorized(Message, Path), + +// #[error("parse error: {0}")] +// ParseError(Message), + +// #[error("tonic error: {0}")] +// TonicError(Message), + +// #[error("mongodb value access error: {0}")] +// MongoDbValueAccessError(ValueAccessError), + +// #[error("mongodb bson serde error: {0}")] +// MongoDbBsonSerError(mongodb::bson::ser::Error), + +// #[error("mongodb value access error: {0}")] +// MongoDbOperateError(mongodb::error::Error), + +// #[error("redis error: {0}")] +// RedisError(redis::RedisError), + +// #[error("io error: {0}")] +// IOError(std::io::Error), + +// #[error("reqwest error: {0}")] +// ReqwestError(reqwest::Error), + +// #[error("service not found: {0}")] +// ServiceNotFound(String), + +// #[error("invalid register code ")] +// InvalidRegisterCode, + +// #[error("bad request: {0}")] +// BadRequest(String), + +// #[error("account or password error")] +// AccountOrPassword, +// } + +// impl From for Error { +// fn from(value: std::io::Error) -> Self { +// Self::IOError(value) +// } +// } + +// impl From for Error { +// fn from(value: redis::RedisError) -> Self { +// Self::RedisError(value) +// } +// } + +// impl From for Error { +// fn from(value: serde_yaml::Error) -> Self { +// Self::ConfigParseError(value) +// } +// } + +// impl From for Error { +// fn from(value: reqwest::Error) -> Self { +// Self::ReqwestError(value) +// } +// } + +// impl From for Error { +// fn from(value: ValueAccessError) -> Self { +// Self::MongoDbValueAccessError(value) +// } +// } + +// impl From for Error { +// fn from(value: mongodb::bson::ser::Error) -> Self { +// Self::MongoDbBsonSerError(value) +// } +// } + +// impl From for Error { +// fn from(value: mongodb::error::Error) -> Self { +// Self::MongoDbOperateError(value) +// } +// } + +// // convert sqlx::Error to Error::ConfilictReservation +// impl From for Error { +// fn from(e: sqlx::Error) -> Self { +// Error::DbError(e) +// } +// } + +// impl From for Error { +// fn from(value: serde_json::Error) -> Self { +// Self::ParseError(value.to_string()) +// } +// } + +// // convert abi::Error to tonic::Status +// impl From for Status { +// fn from(e: Error) -> Self { +// // log the error details +// error!("{:?}", e); +// match e { +// Error::DbError(e) => Status::internal(e.to_string()), +// Error::UnknownError => Status::unknown(e.to_string()), +// Error::ConfigReadError | Error::ConfigParseError(_) => Status::internal(e.to_string()), +// Error::NotFound => Status::not_found(e.to_string()), +// Error::InternalServer(msg) => Status::internal(msg), +// Error::BodyParsing(_, _) => Status::invalid_argument(e.to_string()), +// Error::PathParsing(_, _) => Status::invalid_argument(e.to_string()), +// Error::UnAuthorized(_, _) => Status::unauthenticated(e.to_string()), +// Error::BroadCastError => Status::internal(e.to_string()), +// Error::ParseError(e) => Status::internal(e.to_string()), +// Error::TonicError(e) => Status::internal(e.to_string()), +// Error::MongoDbValueAccessError(e) => Status::internal(e.to_string()), +// Error::MongoDbOperateError(e) => Status::internal(e.to_string()), +// Error::MongoDbBsonSerError(e) => Status::internal(e.to_string()), +// Error::RedisError(_) => Status::internal(e.to_string()), +// Error::ReqwestError(_) => Status::internal(e.to_string()), +// Error::IOError(_) => Status::internal(e.to_string()), +// Error::ServiceNotFound(_) => Status::internal(e.to_string()), +// Error::InvalidRegisterCode => Status::invalid_argument(e.to_string()), +// Error::BadRequest(_) => Status::invalid_argument(e.to_string()), +// Error::AccountOrPassword => Status::invalid_argument(e.to_string()), +// } +// } +// } + +// impl From for Error { +// fn from(status: Status) -> Self { +// let message = status.message().to_string(); +// match status.code() { +// Code::Ok => Error::UnknownError, // 根据需要处理 Ok 状态 +// Code::Cancelled => Error::InternalServer(message), +// Code::Unknown => Error::InternalServer(message), +// Code::InvalidArgument => Error::BodyParsing(message, Path::default()), +// Code::DeadlineExceeded => Error::InternalServer(message), +// Code::NotFound => Error::NotFound, +// Code::AlreadyExists => Error::InternalServer(message), +// Code::PermissionDenied => Error::InternalServer(message), +// Code::ResourceExhausted => Error::InternalServer(message), +// Code::FailedPrecondition => Error::InternalServer(message), +// Code::Aborted => Error::InternalServer(message), +// Code::OutOfRange => Error::InternalServer(message), +// Code::Unimplemented => Error::InternalServer(message), +// Code::Internal => Error::InternalServer(message), +// Code::Unavailable => Error::InternalServer(message), +// Code::DataLoss => Error::InternalServer(message), +// Code::Unauthenticated => Error::UnAuthorized(message, Path::default()), +// } +// } +// } + +// impl IntoResponse for Error { +// fn into_response(self) -> Response { +// let status_code = match self { +// Error::UnknownError => StatusCode::INTERNAL_SERVER_ERROR, +// Error::BodyParsing(_, _) => StatusCode::BAD_REQUEST, +// Error::PathParsing(_, _) => StatusCode::BAD_REQUEST, +// Error::UnAuthorized(_, _) => StatusCode::UNAUTHORIZED, +// Error::NotFound => StatusCode::NOT_FOUND, +// Error::DbError(_) => StatusCode::INTERNAL_SERVER_ERROR, +// Error::ParseError(_) | Error::ConfigReadError => StatusCode::INTERNAL_SERVER_ERROR, +// Error::ConfigParseError(_) => StatusCode::INTERNAL_SERVER_ERROR, +// Error::TonicError(_) => StatusCode::INTERNAL_SERVER_ERROR, +// Error::MongoDbValueAccessError(_) => StatusCode::INTERNAL_SERVER_ERROR, +// Error::MongoDbOperateError(_) => StatusCode::INTERNAL_SERVER_ERROR, +// Error::MongoDbBsonSerError(_) => StatusCode::INTERNAL_SERVER_ERROR, +// Error::RedisError(_) => StatusCode::INTERNAL_SERVER_ERROR, +// Error::ReqwestError(_) => StatusCode::INTERNAL_SERVER_ERROR, +// Error::IOError(_) => StatusCode::INTERNAL_SERVER_ERROR, +// Error::ServiceNotFound(_) => StatusCode::INTERNAL_SERVER_ERROR, +// Error::InternalServer(_) => StatusCode::INTERNAL_SERVER_ERROR, +// Error::BroadCastError => StatusCode::INTERNAL_SERVER_ERROR, +// Error::InvalidRegisterCode => StatusCode::BAD_REQUEST, +// Error::BadRequest(_) => StatusCode::BAD_REQUEST, +// Error::AccountOrPassword => StatusCode::UNAUTHORIZED, +// }; +// let msg = self.to_string(); + +// (status_code, Json(json!({"error": msg}))).into_response() +// } +// } +// impl IntoResponse for Error { +// fn into_response(self) -> Response { +// let (status, msg) = match self { +// Error::UnknownError => ( +// StatusCode::INTERNAL_SERVER_ERROR, +// "UNKNOWN ERROR".to_string(), +// ), +// Error::BodyParsing(msg, path) => ( +// StatusCode::BAD_REQUEST, +// format!("Bad Request errors: {{ message: {}, path: {}}}", msg, path), +// ), +// Error::PathParsing(msg, location) => { +// let mut msg = format!("Bad Request errors: {}", msg); +// if location.is_some() { +// msg = format!("Bad Request errors: in {} : {}", location.unwrap(), msg); +// } +// (StatusCode::BAD_REQUEST, msg) +// } +// Error::UnAuthorized(msg, path) => ( +// StatusCode::UNAUTHORIZED, +// format!("Bad Request errors: {{ message: {}, path: {}}}", msg, path), +// ), +// Error::NotFound => (StatusCode::NOT_FOUND, "NOT FOUND".to_string()), +// Error::DbError(e) => ( +// StatusCode::INTERNAL_SERVER_ERROR, +// format!("INTERNAL SERVER ERROR {:?}", e), +// ), +// Error::ParseError(_) | Error::ConfigReadError => ( +// StatusCode::INTERNAL_SERVER_ERROR, +// "INTERNAL SERVER ERROR ".to_string(), +// ), +// Error::ConfigParseError(e) => ( +// StatusCode::INTERNAL_SERVER_ERROR, +// format!("INTERNAL SERVER ERROR {e}"), +// ), +// Error::TonicError(e) => ( +// StatusCode::INTERNAL_SERVER_ERROR, +// format!("INTERNAL SERVER ERROR {e}"), +// ), +// Error::MongoDbValueAccessError(e) => ( +// StatusCode::INTERNAL_SERVER_ERROR, +// format!("INTERNAL SERVER ERROR {:?}", e), +// ), +// Error::MongoDbOperateError(e) => ( +// StatusCode::INTERNAL_SERVER_ERROR, +// format!("INTERNAL SERVER ERROR {e}"), +// ), +// Error::MongoDbBsonSerError(e) => ( +// StatusCode::INTERNAL_SERVER_ERROR, +// format!("INTERNAL SERVER ERROR {e}"), +// ), +// Error::RedisError(e) => ( +// StatusCode::INTERNAL_SERVER_ERROR, +// format!("INTERNAL SERVER ERROR {:?}", e), +// ), +// Error::ReqwestError(e) => ( +// StatusCode::INTERNAL_SERVER_ERROR, +// format!("INTERNAL SERVER ERROR {e}"), +// ), +// Error::IOError(e) => ( +// StatusCode::INTERNAL_SERVER_ERROR, +// format!("INTERNAL SERVER ERROR {e}"), +// ), +// Error::ServiceNotFound(e) => ( +// StatusCode::INTERNAL_SERVER_ERROR, +// format!("INTERNAL SERVER ERROR {e}"), +// ), +// Error::InternalServer(e) => ( +// StatusCode::INTERNAL_SERVER_ERROR, +// format!("INTERNAL SERVER ERROR {e}"), +// ), +// Error::BroadCastError => ( +// StatusCode::INTERNAL_SERVER_ERROR, +// "BROADCAST ERROR".to_string(), +// ), +// Error::InvalidRegisterCode => { +// (StatusCode::BAD_REQUEST, "INVALID REGISTER CODE".to_string()) +// } +// Error::BadRequest(msg) => ( +// StatusCode::BAD_REQUEST, +// format!("Bad Request errors: {msg}"), +// ), +// Error::AccountOrPassword => ( +// StatusCode::UNAUTHORIZED, +// "INVALID ACCOUNT OR PASSWORD".to_string(), +// ), +// }; +// error!("http request api error: {:?}", msg); +// (status, Json(json!({"message":msg}))).into_response() +// } +// } + +use aws_sdk_s3::error::SdkError; +use axum::{ + http::StatusCode, + response::{IntoResponse, Json}, +}; use mongodb::bson::document::ValueAccessError; -use serde_json::json; +use serde::Serialize; +use std::error::Error as StdError; +use std::fmt; +use tonic::Status; use tracing::error; -type Message = String; -type Location = String; -type Path = String; - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("unknown errors")] +#[derive(Debug, Serialize)] +pub enum ErrorKind { UnknownError, + DbError, + ConfigReadError, + ConfigParseError, + NotFound, + BroadCastError, + InternalServer, + BodyParsing, + PathParsing, + UnAuthorized, + ParseError, + TonicError, + MongoDbValueAccessError, + MongoDbBsonSerError, + MongoDbOperateError, + RedisError, + IOError, + ReqwestError, + ServiceNotFound, + InvalidRegisterCode, + BadRequest, + AccountOrPassword, + OSSError, + CodeIsExpired, + CodeIsInvalid, + BinCode, +} - #[error("database errors{0}")] - DbError(sqlx::Error), +#[derive(Debug, Serialize)] +pub struct Error { + kind: ErrorKind, + details: Option, + #[serde(skip)] + source: Option>, +} - #[error("config file read errors")] - ConfigReadError, +impl Error { + #[inline] + pub fn new( + kind: ErrorKind, + details: impl Into, + source: impl StdError + 'static + Send + Sync, + ) -> Self { + Self { + kind, + source: Some(Box::new(source)), + details: Some(details.into()), + } + } - #[error("config parse errors")] - ConfigParseError(serde_yaml::Error), + #[inline] + pub fn with_kind(kind: ErrorKind) -> Self { + Self { + kind, + source: None, + details: None, + } + } - #[error("not found")] - NotFound, + #[inline] + pub fn with_details(kind: ErrorKind, details: impl Into) -> Self { + Self { + kind, + source: None, + details: Some(details.into()), + } + } - #[error("broadcast errors")] - BroadCastError, + #[inline] + pub fn internal_box(error: Box) -> Self { + Self { + kind: ErrorKind::InternalServer, + details: Some(error.to_string()), + source: Some(error), + } + } - // 500 - #[error("internal server errors")] - InternalServer(Message), + #[inline] + pub fn internal(error: impl StdError + 'static + Send + Sync) -> Self { + Self { + kind: ErrorKind::InternalServer, + details: Some(error.to_string()), + source: Some(Box::new(error)), + } + } - // 400 - #[error("body parsing errors")] - BodyParsing(Message, Path), + #[inline] + pub fn broadcast(error: Box) -> Self { + Self { + kind: ErrorKind::BroadCastError, + details: Some(error.to_string()), + source: Some(error), + } + } - #[error("path parsing errors{0}")] - PathParsing(Message, Option), + #[inline] + pub fn internal_with_details(details: impl Into) -> Self { + Self::with_details(ErrorKind::InternalServer, details) + } - #[error("unauthorized request{0}, path: {1}")] - UnAuthorized(Message, Path), + #[inline] + pub fn service_not_found(name: impl Into) -> Self { + Self::with_details(ErrorKind::ServiceNotFound, name) + } - #[error("parse error: {0}")] - ParseError(Message), + #[inline] + pub fn unauthorized( + error: impl StdError + 'static + Send + Sync, + details: impl Into, + ) -> Self { + Self::new(ErrorKind::UnAuthorized, details, error) + } - #[error("rpc error: {0}")] - TonicError(Message), + #[inline] + pub fn unauthorized_with_details(details: impl Into) -> Self { + Self::with_details(ErrorKind::UnAuthorized, details) + } - #[error("mongodb value access error: {0}")] - MongoDbValueAccessError(ValueAccessError), + #[inline] + pub fn bad_request(details: impl Into) -> Self { + Self::with_details(ErrorKind::BadRequest, details) + } - #[error("mongodb value access error: {0}")] - MongoDbBsonSerError(mongodb::bson::ser::Error), + #[inline] + pub fn code_invalid(details: impl Into) -> Self { + Self::with_details(ErrorKind::CodeIsInvalid, details) + } - #[error("mongodb value access error: {0}")] - MongoDbOperateError(mongodb::error::Error), + #[inline] + pub fn code_expired(details: impl Into) -> Self { + Self::with_details(ErrorKind::CodeIsExpired, details) + } - #[error("redis error: {0}")] - RedisError(redis::RedisError), + #[inline] + pub fn db_not_found(details: impl Into) -> Self { + Self::with_details(ErrorKind::DbError, details) + } - #[error("reqwest error: {0}")] - IOError(std::io::Error), + #[inline] + pub fn not_found() -> Self { + Self::with_kind(ErrorKind::NotFound) + } - #[error("reqwest error: {0}")] - ReqwestError(reqwest::Error), + #[inline] + pub fn not_found_with_details(details: impl Into) -> Self { + Self::with_details(ErrorKind::NotFound, details) + } - #[error("SERVICE NOT FOUND: {0}")] - ServiceNotFound(String), + #[inline] + pub fn account_or_pwd() -> Self { + Self::with_kind(ErrorKind::AccountOrPassword) + } - #[error("invalid register code ")] - InvalidRegisterCode, + #[inline] + pub fn body_parsing(details: impl Into) -> Self { + Self::with_details(ErrorKind::BodyParsing, details) + } - #[error("bad request: {0}")] - BadRequest(String), + #[inline] + pub fn path_parsing(err: impl StdError + 'static + Send + Sync) -> Self { + Self::new(ErrorKind::PathParsing, err.to_string(), err) + } +} - #[error("account or password error")] - AccountOrPassword, +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match &self.details { + Some(details) => write!(f, "{:?}: {}", self.kind, details), + None => write!(f, "{:?}", self.kind), + } + } +} + +impl StdError for Error { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + self.source + .as_deref() + .map(|e| e as &(dyn StdError + 'static)) + } +} + +impl From for Status { + fn from(e: Error) -> Self { + let code = match e.kind { + ErrorKind::UnknownError => tonic::Code::Unknown, + ErrorKind::DbError => tonic::Code::Internal, + ErrorKind::ConfigReadError => tonic::Code::Internal, + ErrorKind::ConfigParseError => tonic::Code::Internal, + ErrorKind::NotFound => tonic::Code::NotFound, + ErrorKind::BroadCastError => tonic::Code::Internal, + ErrorKind::InternalServer => tonic::Code::Internal, + ErrorKind::BodyParsing => tonic::Code::InvalidArgument, + ErrorKind::PathParsing => tonic::Code::InvalidArgument, + ErrorKind::UnAuthorized => tonic::Code::Unauthenticated, + ErrorKind::ParseError => tonic::Code::Internal, + ErrorKind::TonicError => tonic::Code::Internal, + ErrorKind::MongoDbValueAccessError => tonic::Code::Internal, + ErrorKind::MongoDbBsonSerError => tonic::Code::Internal, + ErrorKind::MongoDbOperateError => tonic::Code::Internal, + ErrorKind::RedisError => tonic::Code::Internal, + ErrorKind::IOError => tonic::Code::Internal, + ErrorKind::ReqwestError => tonic::Code::Internal, + ErrorKind::ServiceNotFound => tonic::Code::Internal, + ErrorKind::InvalidRegisterCode => tonic::Code::InvalidArgument, + ErrorKind::BadRequest => tonic::Code::InvalidArgument, + ErrorKind::AccountOrPassword => tonic::Code::Unauthenticated, + ErrorKind::OSSError => tonic::Code::Internal, + ErrorKind::CodeIsExpired => tonic::Code::InvalidArgument, + ErrorKind::CodeIsInvalid => tonic::Code::InvalidArgument, + ErrorKind::BinCode => tonic::Code::Internal, + }; + + error!("gRPC procedure encountered error{:?}", e); + let kind = format!("{:?}", e.kind); + let details = e.details.unwrap_or_default(); + Status::with_details(code, &kind, details.into()) + } +} + +impl From for Error { + fn from(status: Status) -> Self { + let kind = match status.message() { + "UnknownError" => ErrorKind::UnknownError, + "DbError" => ErrorKind::DbError, + "ConfigReadError" => ErrorKind::ConfigReadError, + "ConfigParseError" => ErrorKind::ConfigParseError, + "NotFound" => ErrorKind::NotFound, + "BroadCastError" => ErrorKind::BroadCastError, + "InternalServer" => ErrorKind::InternalServer, + "BodyParsing" => ErrorKind::BodyParsing, + "PathParsing" => ErrorKind::PathParsing, + "UnAuthorized" => ErrorKind::UnAuthorized, + "ParseError" => ErrorKind::ParseError, + "TonicError" => ErrorKind::TonicError, + "MongoDbValueAccessError" => ErrorKind::MongoDbValueAccessError, + "MongoDbOperateError" => ErrorKind::MongoDbOperateError, + "MongoDbBsonSerError" => ErrorKind::MongoDbBsonSerError, + "RedisError" => ErrorKind::RedisError, + "IOError" => ErrorKind::IOError, + "ReqwestError" => ErrorKind::ReqwestError, + "ServiceNotFound" => ErrorKind::ServiceNotFound, + "InvalidRegisterCode" => ErrorKind::InvalidRegisterCode, + "BadRequest" => ErrorKind::BadRequest, + "AccountOrPassword" => ErrorKind::AccountOrPassword, + "OSSError" => ErrorKind::OSSError, + "CodeIsExpired" => ErrorKind::CodeIsExpired, + "CodeIsInvalid" => ErrorKind::CodeIsInvalid, + "BinCode" => ErrorKind::BinCode, + _ => ErrorKind::UnknownError, // Default to UnknownError if the kind is not recognized + }; + + let details = match String::from_utf8(status.details().to_vec()) { + Ok(details) => Some(details), + Err(_) => None, + }; + + Self { + kind, + details, + source: None, + } + } +} + +impl IntoResponse for Error { + fn into_response(self) -> axum::response::Response { + let status_code = match self.kind { + ErrorKind::UnknownError => StatusCode::INTERNAL_SERVER_ERROR, + ErrorKind::BodyParsing => StatusCode::BAD_REQUEST, + ErrorKind::PathParsing => StatusCode::BAD_REQUEST, + ErrorKind::UnAuthorized => StatusCode::UNAUTHORIZED, + ErrorKind::NotFound => StatusCode::NOT_FOUND, + ErrorKind::DbError => StatusCode::INTERNAL_SERVER_ERROR, + ErrorKind::ParseError | ErrorKind::ConfigReadError => StatusCode::INTERNAL_SERVER_ERROR, + ErrorKind::ConfigParseError => StatusCode::INTERNAL_SERVER_ERROR, + ErrorKind::TonicError => StatusCode::INTERNAL_SERVER_ERROR, + ErrorKind::MongoDbValueAccessError => StatusCode::INTERNAL_SERVER_ERROR, + ErrorKind::MongoDbOperateError => StatusCode::INTERNAL_SERVER_ERROR, + ErrorKind::MongoDbBsonSerError => StatusCode::INTERNAL_SERVER_ERROR, + ErrorKind::RedisError => StatusCode::INTERNAL_SERVER_ERROR, + ErrorKind::ReqwestError => StatusCode::INTERNAL_SERVER_ERROR, + ErrorKind::IOError => StatusCode::INTERNAL_SERVER_ERROR, + ErrorKind::ServiceNotFound => StatusCode::INTERNAL_SERVER_ERROR, + ErrorKind::InternalServer => StatusCode::INTERNAL_SERVER_ERROR, + ErrorKind::BroadCastError => StatusCode::INTERNAL_SERVER_ERROR, + ErrorKind::InvalidRegisterCode => StatusCode::BAD_REQUEST, + ErrorKind::BadRequest => StatusCode::BAD_REQUEST, + ErrorKind::AccountOrPassword => StatusCode::UNAUTHORIZED, + ErrorKind::OSSError => StatusCode::INTERNAL_SERVER_ERROR, + ErrorKind::CodeIsExpired => StatusCode::BAD_REQUEST, + ErrorKind::CodeIsInvalid => StatusCode::BAD_REQUEST, + ErrorKind::BinCode => StatusCode::INTERNAL_SERVER_ERROR, + }; + + // todo is need to log error? + error!("custom error to http error{:?}", self); + (status_code, Json(self)).into_response() + } } impl From for Error { fn from(value: std::io::Error) -> Self { - Self::IOError(value) + Self::new(ErrorKind::IOError, value.to_string(), value) } } impl From for Error { fn from(value: redis::RedisError) -> Self { - Self::RedisError(value) + Self::new(ErrorKind::RedisError, value.to_string(), value) } } impl From for Error { fn from(value: serde_yaml::Error) -> Self { - Self::ConfigParseError(value) + Self::new(ErrorKind::ConfigParseError, value.to_string(), value) } } impl From for Error { fn from(value: reqwest::Error) -> Self { - Self::ReqwestError(value) + Self::new(ErrorKind::ReqwestError, value.to_string(), value) } } impl From for Error { fn from(value: ValueAccessError) -> Self { - Self::MongoDbValueAccessError(value) + Self::new(ErrorKind::MongoDbValueAccessError, value.to_string(), value) } } impl From for Error { fn from(value: mongodb::bson::ser::Error) -> Self { - Self::MongoDbBsonSerError(value) + Self::new(ErrorKind::MongoDbBsonSerError, value.to_string(), value) } } impl From for Error { fn from(value: mongodb::error::Error) -> Self { - Self::MongoDbOperateError(value) + Self::new(ErrorKind::MongoDbOperateError, value.to_string(), value) } } // convert sqlx::Error to Error::ConfilictReservation impl From for Error { - fn from(e: sqlx::Error) -> Self { - match e { - sqlx::Error::Database(e) => Error::DbError(sqlx::Error::Database(e)), - sqlx::Error::RowNotFound => Error::NotFound, - _ => Error::DbError(e), - } + fn from(value: sqlx::Error) -> Self { + Self::new(ErrorKind::DbError, value.to_string(), value) } } impl From for Error { fn from(value: serde_json::Error) -> Self { - Self::ParseError(value.to_string()) + Self::new(ErrorKind::ParseError, value.to_string(), value) } } -// rpc PartialEq for Error { -// fn eq(&self, other: &Self) -> bool { -// match (self, other) { -// (Self::DbError(_), Self::DbError(_)) => true, -// _ => core::mem::discriminant(self) == core::mem::discriminant(other), -// } -// } -// } -// convert abi::Error to tonic::Status -impl From for tonic::Status { - fn from(e: Error) -> Self { - match e { - Error::DbError(e) => tonic::Status::internal(format!("DB errors: {e}")), - - Error::UnknownError => tonic::Status::unknown("Unknown errors"), - - Error::ConfigReadError | Error::ConfigParseError(_) => { - tonic::Status::internal(e.to_string()) - } - Error::NotFound => tonic::Status::not_found("Not found by the given condition"), - Error::InternalServer(msg) => tonic::Status::internal(msg), - Error::BodyParsing(_, _) => tonic::Status::invalid_argument(e.to_string()), - Error::PathParsing(_, _) => tonic::Status::invalid_argument(e.to_string()), - Error::UnAuthorized(_, _) => tonic::Status::unauthenticated(e.to_string()), - Error::BroadCastError => tonic::Status::internal("BROADCAST ERROR"), - Error::ParseError(e) => tonic::Status::internal(format!("PARSE ERROR: {e}")), - Error::TonicError(e) => tonic::Status::internal(format!("TONIC ERROR: {e}")), - Error::MongoDbValueAccessError(e) => { - tonic::Status::internal(format!("MONGODB VALUE ACCESS ERROR: {e}")) - } - Error::MongoDbOperateError(e) => { - tonic::Status::internal(format!("MONGODB OPERATE ERROR: {e}")) - } - Error::MongoDbBsonSerError(e) => { - tonic::Status::internal(format!("MONGODB BSON SER ERROR: {e}")) - } - Error::RedisError(_) => tonic::Status::internal(format!("REDIS ERROR: {e}")), - Error::ReqwestError(_) => tonic::Status::internal(format!("REDIS ERROR: {e}")), - Error::IOError(_) => tonic::Status::internal(format!("IO ERROR: {e}")), - Error::ServiceNotFound(_) => tonic::Status::internal(format!("SERVICE NOT FOUND: {e}")), - Error::InvalidRegisterCode => { - tonic::Status::invalid_argument(format!("REGISTER ERROR: {e}")) - } - Error::BadRequest(_) => tonic::Status::invalid_argument(format!(" BAD REQUEST: {e}")), - Error::AccountOrPassword => { - tonic::Status::invalid_argument(" INVALID ACCOUNT OR PASSWORD".to_string()) - } - } +impl From for Error { + fn from(value: tonic::transport::Error) -> Self { + Self::new(ErrorKind::TonicError, value.to_string(), value) } } -impl IntoResponse for Error { - fn into_response(self) -> Response { - let (status, msg) = match self { - Error::UnknownError => ( - StatusCode::INTERNAL_SERVER_ERROR, - "UNKNOWN ERROR".to_string(), - ), - Error::BodyParsing(msg, path) => ( - StatusCode::BAD_REQUEST, - format!("Bad Request errors: {{ message: {}, path: {}}}", msg, path), - ), - Error::PathParsing(msg, location) => { - let mut msg = format!("Bad Request errors: {}", msg); - if location.is_some() { - msg = format!("Bad Request errors: in {} : {}", location.unwrap(), msg); - } - (StatusCode::BAD_REQUEST, msg) - } - Error::UnAuthorized(msg, path) => ( - StatusCode::UNAUTHORIZED, - format!("Bad Request errors: {{ message: {}, path: {}}}", msg, path), - ), - Error::NotFound => (StatusCode::NOT_FOUND, "NOT FOUND".to_string()), - Error::DbError(e) => ( - StatusCode::INTERNAL_SERVER_ERROR, - format!("INTERNAL SERVER ERROR {:?}", e), - ), - Error::ParseError(_) | Error::ConfigReadError => ( - StatusCode::INTERNAL_SERVER_ERROR, - "INTERNAL SERVER ERROR ".to_string(), - ), - Error::ConfigParseError(e) => ( - StatusCode::INTERNAL_SERVER_ERROR, - format!("INTERNAL SERVER ERROR {e}"), - ), - Error::TonicError(e) => ( - StatusCode::INTERNAL_SERVER_ERROR, - format!("INTERNAL SERVER ERROR {e}"), - ), - Error::MongoDbValueAccessError(e) => ( - StatusCode::INTERNAL_SERVER_ERROR, - format!("INTERNAL SERVER ERROR {:?}", e), - ), - Error::MongoDbOperateError(e) => ( - StatusCode::INTERNAL_SERVER_ERROR, - format!("INTERNAL SERVER ERROR {e}"), - ), - Error::MongoDbBsonSerError(e) => ( - StatusCode::INTERNAL_SERVER_ERROR, - format!("INTERNAL SERVER ERROR {e}"), - ), - Error::RedisError(e) => ( - StatusCode::INTERNAL_SERVER_ERROR, - format!("INTERNAL SERVER ERROR {:?}", e), - ), - Error::ReqwestError(e) => ( - StatusCode::INTERNAL_SERVER_ERROR, - format!("INTERNAL SERVER ERROR {e}"), - ), - Error::IOError(e) => ( - StatusCode::INTERNAL_SERVER_ERROR, - format!("INTERNAL SERVER ERROR {e}"), - ), - Error::ServiceNotFound(e) => ( - StatusCode::INTERNAL_SERVER_ERROR, - format!("INTERNAL SERVER ERROR {e}"), - ), - Error::InternalServer(e) => ( - StatusCode::INTERNAL_SERVER_ERROR, - format!("INTERNAL SERVER ERROR {e}"), - ), - Error::BroadCastError => ( - StatusCode::INTERNAL_SERVER_ERROR, - "BROADCAST ERROR".to_string(), - ), - Error::InvalidRegisterCode => { - (StatusCode::BAD_REQUEST, "INVALID REGISTER CODE".to_string()) - } - Error::BadRequest(msg) => ( - StatusCode::BAD_REQUEST, - format!("Bad Request errors: {msg}"), - ), - Error::AccountOrPassword => ( - StatusCode::UNAUTHORIZED, - "INVALID ACCOUNT OR PASSWORD".to_string(), - ), - }; - error!("http request api error: {:?}", msg); - (status, Json(json!({"message":msg}))).into_response() +/// SdkError is not Send and Sync, so we just extract the details +impl From> for Error +where + E: StdError + 'static, +{ + fn from(sdk_error: SdkError) -> Self { + let kind = ErrorKind::OSSError; + + let details = sdk_error.to_string(); + + Self::with_details(kind, details) + } +} + +impl From for Error { + fn from(value: bincode::Error) -> Self { + Self::new(ErrorKind::BinCode, value.to_string(), value) } } diff --git a/abi/src/types/msg.rs b/abi/src/types/msg.rs index 384f275..87bc9ed 100644 --- a/abi/src/types/msg.rs +++ b/abi/src/types/msg.rs @@ -1,7 +1,7 @@ use mongodb::bson::Document; use tonic::Status; -use crate::errors::Error; +use crate::errors::{Error, ErrorKind}; use crate::message::{ GetDbMessagesRequest, GetDbMsgRequest, GroupMemSeq, Msg, MsgResponse, MsgType, SaveGroupMsgRequest, SaveMessageRequest, SendMsgRequest, UserAndGroupId, @@ -205,16 +205,25 @@ impl UserAndGroupId { impl GetDbMsgRequest { pub fn validate(&self) -> Result<(), Error> { if self.user_id.is_empty() { - return Err(Error::BadRequest("user_id is empty".to_string())); + return Err(Error::with_details( + ErrorKind::BadRequest, + "user_id is empty", + )); } if self.start < 0 { - return Err(Error::BadRequest("start is invalid".to_string())); + return Err(Error::with_details( + ErrorKind::BadRequest, + "start is invalid".to_string(), + )); } if self.end < 0 { - return Err(Error::BadRequest("end is invalid".to_string())); + return Err(Error::with_details(ErrorKind::BadRequest, "end is invalid")); } if self.end < self.start { - return Err(Error::BadRequest("start is greater than end".to_string())); + return Err(Error::with_details( + ErrorKind::BadRequest, + "start is greater than end", + )); } Ok(()) } @@ -223,21 +232,66 @@ impl GetDbMsgRequest { impl GetDbMessagesRequest { pub fn validate(&self) -> Result<(), Error> { if self.user_id.is_empty() { - return Err(Error::BadRequest("user_id is empty".to_string())); + return Err(Error::with_details( + ErrorKind::BadRequest, + "user_id is empty", + )); } if self.start < 0 { - return Err(Error::BadRequest("start is invalid".to_string())); + return Err(Error::with_details( + ErrorKind::BadRequest, + "start is invalid", + )); } if self.end < 0 { - return Err(Error::BadRequest("end is invalid".to_string())); + return Err(Error::with_details(ErrorKind::BadRequest, "end is invalid")); } if self.end < self.start { - return Err(Error::BadRequest("start is greater than end".to_string())); + return Err(Error::with_details( + ErrorKind::BadRequest, + "start is greater than end", + )); } Ok(()) } } +// impl GetDbMsgRequest { +// pub fn validate(&self) -> Result<(), Error> { +// if self.user_id.is_empty() { +// return Err(Error::BadRequest("user_id is empty".to_string())); +// } +// if self.start < 0 { +// return Err(Error::BadRequest("start is invalid".to_string())); +// } +// if self.end < 0 { +// return Err(Error::BadRequest("end is invalid".to_string())); +// } +// if self.end < self.start { +// return Err(Error::BadRequest("start is greater than end".to_string())); +// } +// Ok(()) +// } +// } + +// impl GetDbMessagesRequest { +// pub fn validate(&self) -> Result<(), Error> { +// if self.user_id.is_empty() { +// return Err(Error::BadRequest("user_id is empty".to_string())); +// } +// if self.start < 0 { +// return Err(Error::BadRequest("start is invalid".to_string())); +// } +// if self.end < 0 { +// return Err(Error::BadRequest("end is invalid".to_string())); +// } +// if self.end < self.start { +// return Err(Error::BadRequest("start is greater than end".to_string())); +// } +// Ok(()) +// } +// } + impl SaveMessageRequest { pub fn new(msg: Msg, need_to_history: bool) -> Self { Self { diff --git a/api/src/api_utils/custom_extract/auth.rs b/api/src/api_utils/custom_extract/auth.rs index 3c64547..41f4e2c 100644 --- a/api/src/api_utils/custom_extract/auth.rs +++ b/api/src/api_utils/custom_extract/auth.rs @@ -1,4 +1,3 @@ -use axum::extract::path::ErrorKind; use axum::extract::rejection::{JsonRejection, PathRejection}; use axum::extract::{FromRef, FromRequestParts, Request}; use axum::http::request::Parts; @@ -53,7 +52,7 @@ where if !header.starts_with(BEARER) { return Err(( StatusCode::UNAUTHORIZED, - Error::UnAuthorized("UnAuthorized Request".to_string(), path), + Error::unauthorized_with_details(path), )); } let header: Vec<&str> = header.split_whitespace().collect(); @@ -63,10 +62,7 @@ where &DecodingKey::from_secret(app_state.jwt_secret.as_bytes()), &Validation::default(), ) { - return Err(( - StatusCode::INTERNAL_SERVER_ERROR, - Error::InternalServer(err.to_string()), - )); + return Err((StatusCode::INTERNAL_SERVER_ERROR, Error::internal(err))); } let req = Request::from_parts(parts, body); @@ -75,14 +71,14 @@ where Ok(value) => Ok(Self(value.0)), // convert the errors from `axum::Json` into whatever we want Err(rejection) => { - let app_err = Error::BodyParsing(rejection.body_text(), path); + let app_err = Error::body_parsing(rejection.body_text()); Err((rejection.status(), app_err)) } } } else { Err(( StatusCode::UNAUTHORIZED, - Error::UnAuthorized("UnAuthorized Request".to_string(), path), + Error::unauthorized_with_details(path), )) } } @@ -115,7 +111,7 @@ where if !header.starts_with(BEARER) { return Err(( StatusCode::UNAUTHORIZED, - Error::UnAuthorized("UnAuthorized Request".to_string(), path), + Error::unauthorized_with_details(path), )); } @@ -126,10 +122,7 @@ where &DecodingKey::from_secret(app_state.jwt_secret.as_bytes()), &Validation::default(), ) { - return Err(( - StatusCode::UNAUTHORIZED, - Error::UnAuthorized(err.to_string(), path), - )); + return Err((StatusCode::UNAUTHORIZED, Error::unauthorized(err, path))); } match axum::extract::Path::::from_request_parts(parts, state).await { @@ -137,56 +130,56 @@ where Err(rejection) => { let (status, body) = match rejection { PathRejection::FailedToDeserializePathParams(inner) => { - let mut status = StatusCode::BAD_REQUEST; - - let kind = inner.into_kind(); - let body = match &kind { - ErrorKind::WrongNumberOfParameters { .. } => { - Error::PathParsing(kind.to_string(), None) - } - - ErrorKind::ParseErrorAtKey { key, .. } => { - Error::PathParsing(kind.to_string(), Some(key.clone())) - } - - ErrorKind::ParseErrorAtIndex { index, .. } => { - Error::PathParsing(kind.to_string(), Some(index.to_string())) - } - - ErrorKind::ParseError { .. } => { - Error::PathParsing(kind.to_string(), None) - } - - ErrorKind::InvalidUtf8InPathParam { key } => { - Error::PathParsing(kind.to_string(), Some(key.clone())) - } - - ErrorKind::UnsupportedType { .. } => { - // these errors are caused by the programmer using an unsupported type - // (such as nested maps) so respond with `500` instead - status = StatusCode::INTERNAL_SERVER_ERROR; - Error::InternalServer(kind.to_string()) - } - - ErrorKind::Message(msg) => Error::PathParsing(msg.clone(), None), - _ => Error::PathParsing( - format!("Unhandled deserialization errors: {kind}"), - None, - ), - }; + let status = StatusCode::BAD_REQUEST; + + // let kind = inner.into_kind(); + let body = Error::path_parsing(inner); + // let body = match &kind { + // ErrorKind::WrongNumberOfParameters { .. } => { + // Error::PathParsing(kind.to_string(), None) + // } + + // ErrorKind::ParseErrorAtKey { key, .. } => { + // Error::PathParsing(kind.to_string(), Some(key.clone())) + // } + + // ErrorKind::ParseErrorAtIndex { index, .. } => { + // Error::PathParsing(kind.to_string(), Some(index.to_string())) + // } + + // ErrorKind::ParseError { .. } => { + // Error::PathParsing(kind.to_string(), None) + // } + + // ErrorKind::InvalidUtf8InPathParam { key } => { + // Error::PathParsing(kind.to_string(), Some(key.clone())) + // } + + // ErrorKind::UnsupportedType { .. } => { + // // these errors are caused by the programmer using an unsupported type + // // (such as nested maps) so respond with `500` instead + // status = StatusCode::INTERNAL_SERVER_ERROR; + // Error::InternalServer(kind.to_string()) + // } + + // ErrorKind::Message(msg) => Error::PathParsing(msg.clone(), None), + // _ => Error::PathParsing( + // format!("Unhandled deserialization errors: {kind}"), + // None, + // ), + // }; (status, body) } PathRejection::MissingPathParams(error) => ( StatusCode::INTERNAL_SERVER_ERROR, - Error::PathParsing(error.to_string(), None), + Error::path_parsing(error), ), _ => ( StatusCode::INTERNAL_SERVER_ERROR, - Error::PathParsing( - format!("Unhandled path rejection: {rejection}"), - None, - ), + Error::internal_with_details(format!( + "Unhandled path rejection: {rejection}" + )), ), }; @@ -196,7 +189,7 @@ where } else { Err(( StatusCode::UNAUTHORIZED, - Error::UnAuthorized("UnAuthorized Request".to_string(), path), + Error::unauthorized_with_details(path), )) } } diff --git a/api/src/api_utils/custom_extract/json_extractor.rs b/api/src/api_utils/custom_extract/json_extractor.rs index 26ca791..b6d2fa7 100644 --- a/api/src/api_utils/custom_extract/json_extractor.rs +++ b/api/src/api_utils/custom_extract/json_extractor.rs @@ -1,9 +1,8 @@ use abi::errors::Error; use axum::{ async_trait, - extract::{rejection::JsonRejection, FromRequest, MatchedPath, Request}, + extract::{rejection::JsonRejection, FromRequest, Request}, http::StatusCode, - RequestPartsExt, }; pub struct JsonExtractor(pub T); @@ -17,18 +16,18 @@ where type Rejection = (StatusCode, Error); async fn from_request(req: Request, state: &S) -> Result { - let (mut parts, body) = req.into_parts(); + let (parts, body) = req.into_parts(); // We can use other extractors to provide better rejection messages. // For example, here we are using `axum::extract::MatchedPath` to // provide a better errors message. // // Have to run that first since `Json` extraction consumes the request. - let path = parts - .extract::() - .await - .map(|path| path.as_str().to_owned()) - .ok(); + // let path = parts + // .extract::() + // .await + // .map(|path| path.as_str().to_owned()) + // .ok(); let req = Request::from_parts(parts, body); @@ -36,11 +35,11 @@ where Ok(value) => Ok(Self(value.0)), // convert the errors from `axum::Json` into whatever we want Err(rejection) => { - let mut ph = String::new(); - if path.is_some() { - ph = path.unwrap(); - } - let app_err = Error::BodyParsing(rejection.body_text(), ph); + // let mut ph = String::new(); + // if path.is_some() { + // ph = path.unwrap(); + // } + let app_err = Error::body_parsing(rejection.body_text()); Err((rejection.status(), app_err)) } diff --git a/api/src/api_utils/custom_extract/path_extractor.rs b/api/src/api_utils/custom_extract/path_extractor.rs index 568bbd0..8f458d8 100644 --- a/api/src/api_utils/custom_extract/path_extractor.rs +++ b/api/src/api_utils/custom_extract/path_extractor.rs @@ -1,7 +1,7 @@ use abi::errors::Error; use axum::{ async_trait, - extract::{path::ErrorKind, rejection::PathRejection, FromRequestParts}, + extract::{rejection::PathRejection, FromRequestParts}, http::{request::Parts, StatusCode}, }; use serde::de::DeserializeOwned; @@ -24,53 +24,56 @@ where Err(rejection) => { let (status, body) = match rejection { PathRejection::FailedToDeserializePathParams(inner) => { - let mut status = StatusCode::BAD_REQUEST; + let status = StatusCode::BAD_REQUEST; + let body = Error::path_parsing(inner); - let kind = inner.into_kind(); - let body = match &kind { - ErrorKind::WrongNumberOfParameters { .. } => { - Error::PathParsing(kind.to_string(), None) - } + // let kind = inner.into_kind(); + // let body = match &kind { + // ErrorKind::WrongNumberOfParameters { .. } => { + // Error::PathParsing(kind.to_string(), None) + // } - ErrorKind::ParseErrorAtKey { key, .. } => { - Error::PathParsing(kind.to_string(), Some(key.clone())) - } + // ErrorKind::ParseErrorAtKey { key, .. } => { + // Error::PathParsing(kind.to_string(), Some(key.clone())) + // } - ErrorKind::ParseErrorAtIndex { index, .. } => { - Error::PathParsing(kind.to_string(), Some(index.to_string())) - } + // ErrorKind::ParseErrorAtIndex { index, .. } => { + // Error::PathParsing(kind.to_string(), Some(index.to_string())) + // } - ErrorKind::ParseError { .. } => { - Error::PathParsing(kind.to_string(), None) - } + // ErrorKind::ParseError { .. } => { + // Error::PathParsing(kind.to_string(), None) + // } - ErrorKind::InvalidUtf8InPathParam { key } => { - Error::PathParsing(kind.to_string(), Some(key.clone())) - } + // ErrorKind::InvalidUtf8InPathParam { key } => { + // Error::PathParsing(kind.to_string(), Some(key.clone())) + // } - ErrorKind::UnsupportedType { .. } => { - // this errors is caused by the programmer using an unsupported type - // (such as nested maps) so respond with `500` instead - status = StatusCode::INTERNAL_SERVER_ERROR; - Error::InternalServer(kind.to_string()) - } + // ErrorKind::UnsupportedType { .. } => { + // // this errors is caused by the programmer using an unsupported type + // // (such as nested maps) so respond with `500` instead + // status = StatusCode::INTERNAL_SERVER_ERROR; + // Error::internal_with_details(kind.to_string()) + // } - ErrorKind::Message(msg) => Error::PathParsing(msg.clone(), None), - _ => Error::PathParsing( - format!("Unhandled deserialization errors: {kind}"), - None, - ), - }; + // ErrorKind::Message(msg) => Error::PathParsing(msg.clone(), None), + // _ => Error::PathParsing( + // format!("Unhandled deserialization errors: {kind}"), + // None, + // ), + // }; (status, body) } PathRejection::MissingPathParams(error) => ( StatusCode::INTERNAL_SERVER_ERROR, - Error::PathParsing(error.to_string(), None), + Error::path_parsing(error), ), _ => ( StatusCode::INTERNAL_SERVER_ERROR, - Error::PathParsing(format!("Unhandled path rejection: {rejection}"), None), + Error::internal_with_details(format!( + "Unhandled path rejection: {rejection}" + )), ), }; diff --git a/api/src/handlers/files/file.rs b/api/src/handlers/files/file.rs index 11923a7..8d95893 100644 --- a/api/src/handlers/files/file.rs +++ b/api/src/handlers/files/file.rs @@ -14,11 +14,7 @@ pub async fn upload( mut multipart: Multipart, ) -> Result { let mut filename = String::new(); - if let Some(field) = multipart - .next_field() - .await - .map_err(|err| Error::InternalServer(err.to_string()))? - { + if let Some(field) = multipart.next_field().await.map_err(Error::internal)? { filename = field.file_name().unwrap_or_default().to_string(); let extension = Path::new(&filename).extension().and_then(OsStr::to_str); filename = match extension { @@ -26,10 +22,7 @@ pub async fn upload( Some(e) => format!("{}.{}", nanoid!(), e), }; - let data = field - .bytes() - .await - .map_err(|_e| Error::InternalServer(_e.to_string()))?; + let data = field.bytes().await.map_err(Error::internal)?; state.oss.upload_file(&filename, data.into()).await?; } @@ -67,11 +60,7 @@ pub async fn upload_avatar( mut multipart: Multipart, ) -> Result { let mut filename = String::new(); - if let Some(field) = multipart - .next_field() - .await - .map_err(|err| Error::InternalServer(err.to_string()))? - { + if let Some(field) = multipart.next_field().await.map_err(Error::internal)? { filename = field.file_name().unwrap_or_default().to_string(); let extension = Path::new(&filename).extension().and_then(OsStr::to_str); filename = match extension { @@ -79,10 +68,7 @@ pub async fn upload_avatar( Some(e) => format!("{}.{}", nanoid!(), e), }; - let data = field - .bytes() - .await - .map_err(|_e| Error::InternalServer(_e.to_string()))?; + let data = field.bytes().await.map_err(Error::internal)?; state.oss.upload_avatar(&filename, data.into()).await?; } diff --git a/api/src/handlers/friends/friend_handlers.rs b/api/src/handlers/friends/friend_handlers.rs index 7c5176e..f460ae1 100644 --- a/api/src/handlers/friends/friend_handlers.rs +++ b/api/src/handlers/friends/friend_handlers.rs @@ -29,14 +29,12 @@ pub async fn get_friends_list_by_user_id( }; let friends = db_rpc .get_friend_list(request.clone()) - .await - .map_err(|e| Error::InternalServer(e.to_string()))? + .await? .into_inner() .friends; let fs = db_rpc .get_friendship_list(request) - .await - .map_err(|e| Error::InternalServer(e.to_string()))? + .await? .into_inner() .friendships; Ok(Json(FriendShipList { friends, fs })) @@ -53,8 +51,7 @@ pub async fn get_apply_list_by_user_id( user_id, offline_time, }) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + .await?; let list = response.into_inner().friendships; Ok(Json(list)) } @@ -71,19 +68,18 @@ pub async fn create_friendship( .create_friendship(FsCreateRequest { fs_create: Some(new_friend), }) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + .await?; let inner = response.into_inner(); let fs_req = inner .fs_req - .ok_or(Error::InternalServer("create fs error".to_string()))?; + .ok_or(Error::internal_with_details("create fs error"))?; let fs_send = inner .fs_send - .ok_or(Error::InternalServer("send fs error".to_string()))?; + .ok_or(Error::internal_with_details("send fs error"))?; // decode fs - let fs = bincode::serialize(&fs_send).map_err(|e| Error::InternalServer(e.to_string()))?; + let fs = bincode::serialize(&fs_send)?; // increase send sequence let (cur_seq, _, _) = app_state.cache.incr_send_seq(&fs_send.user_id).await?; @@ -92,10 +88,7 @@ pub async fn create_friendship( let msg = SendMsgRequest::new_with_friend_ship_req(fs_send.user_id, receiver_id, fs, cur_seq); let mut chat_rpc = app_state.chat_rpc.clone(); // need to send message to mq, because need to store - chat_rpc - .send_msg(msg) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + chat_rpc.send_msg(msg).await?; Ok(Json(fs_req)) } @@ -109,21 +102,18 @@ pub async fn agree( let request = FsAgreeRequest { fs_reply: Some(agree), }; - let response = db_rpc - .agree_friendship(request) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + let response = db_rpc.agree_friendship(request).await?; let inner = response.into_inner(); let req = inner .req - .ok_or(Error::InternalServer("agree fs error".to_string()))?; + .ok_or(Error::internal_with_details("agree fs error"))?; let send = inner .send - .ok_or(Error::InternalServer("send fs error".to_string()))?; + .ok_or(Error::internal_with_details("send fs error"))?; let send_id = send.friend_id.clone(); // decode friend - let friend = bincode::serialize(&send).map_err(|e| Error::InternalServer(e.to_string()))?; + let friend = bincode::serialize(&send)?; // increase send sequence let (cur_seq, _, _) = app_state.cache.incr_send_seq(&send_id).await?; @@ -136,8 +126,7 @@ pub async fn agree( friend, cur_seq, )) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + .await?; Ok(Json(req)) } @@ -162,28 +151,22 @@ pub async fn delete_friend( JsonWithAuthExtractor(req): JsonWithAuthExtractor, ) -> Result<(), Error> { if req.user_id.is_empty() { - return Err(Error::BadRequest(String::from("user id is none"))); + return Err(Error::bad_request("user id is none")); } if req.friend_id.is_empty() { - return Err(Error::BadRequest(String::from("friend id is none"))); + return Err(Error::bad_request("friend id is none")); } let user_id = req.user_id.clone(); let friend_id = req.friend_id.clone(); let mut db_rpc = app_state.db_rpc.clone(); - db_rpc - .delete_friend(req) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + db_rpc.delete_friend(req).await?; // send message to friend let msg = SendMsgRequest::new_with_friend_del(user_id, friend_id); let mut chat_rpc = app_state.chat_rpc.clone(); - chat_rpc - .send_msg(msg) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + chat_rpc.send_msg(msg).await?; Ok(()) } @@ -192,13 +175,10 @@ pub async fn update_friend_remark( JsonWithAuthExtractor(relation): JsonWithAuthExtractor, ) -> Result<(), Error> { if relation.remark.is_empty() { - return Err(Error::BadRequest(String::from("remark is none"))); + return Err(Error::bad_request("remark is none")); } let mut db_rpc = app_state.db_rpc.clone(); - db_rpc - .update_friend_remark(relation) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + db_rpc.update_friend_remark(relation).await?; Ok(()) } @@ -209,8 +189,7 @@ pub async fn query_friend_info( let mut db_rpc = app_state.db_rpc.clone(); let friend = db_rpc .query_friend_info(QueryFriendInfoRequest { user_id }) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; - let friend = friend.into_inner().friend.ok_or(Error::NotFound)?; + .await?; + let friend = friend.into_inner().friend.ok_or(Error::not_found())?; Ok(Json(friend)) } diff --git a/api/src/handlers/groups/group_handlers.rs b/api/src/handlers/groups/group_handlers.rs index 4c68459..215ae68 100644 --- a/api/src/handlers/groups/group_handlers.rs +++ b/api/src/handlers/groups/group_handlers.rs @@ -23,13 +23,12 @@ pub async fn get_group( let mut db_rpc = app_state.db_rpc.clone(); let resp = db_rpc .get_group(GetGroupRequest::new(user_id, group_id)) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + .await?; let group = resp .into_inner() .group - .ok_or(Error::InternalServer("group not found".to_string()))?; + .ok_or(Error::internal_with_details("group not found"))?; Ok(Json(group)) } @@ -48,13 +47,12 @@ pub async fn get_group_and_members( let resp = db_rpc .get_group_and_members(GetGroupRequest::new(user_id, group_id)) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + .await?; let resp = resp.into_inner(); let group = resp .group - .ok_or(Error::InternalServer("group not found".to_string()))?; + .ok_or(Error::internal_with_details("group not found"))?; Ok(Json(GroupAndMembers { group, @@ -68,10 +66,7 @@ pub async fn get_group_members( ) -> Result>, Error> { let mut db_rpc = app_state.db_rpc.clone(); - let resp = db_rpc - .get_group_members(req) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + let resp = db_rpc.get_group_members(req).await?; Ok(Json(resp.into_inner().members)) } @@ -94,21 +89,16 @@ pub async fn create_group_handler( // send rpc request let request = GroupCreateRequest::new(new_group); let mut db_rpc = app_state.db_rpc.clone(); - let response = db_rpc.group_create(request).await.map_err(|e| { - Error::InternalServer(format!( - "procedure db rpc service error: group_create {:?}", - e - )) - })?; + let response = db_rpc.group_create(request).await?; // decode the invitation to binary let invitation = response .into_inner() .invitation - .ok_or(Error::InternalServer("group create failed".to_string()))?; + .ok_or(Error::internal_with_details("group create failed"))?; let mut chat_rpc = app_state.chat_rpc.clone(); - let msg = bincode::serialize(&invitation).map_err(|e| Error::InternalServer(e.to_string()))?; + let msg = bincode::serialize(&invitation)?; // increase the send sequence for sender let (seq, _, _) = app_state.cache.incr_send_seq(&user_id).await?; @@ -116,12 +106,7 @@ pub async fn create_group_handler( // send the group invitation to the members let request = SendMsgRequest::new_with_group_invitation(user_id, group_id, seq, msg); - chat_rpc.send_msg(request).await.map_err(|e| { - Error::InternalServer(format!( - "procedure chat rpc service error: send_msg {:?}", - e - )) - })?; + chat_rpc.send_msg(request).await?; Ok(Json(invitation)) } @@ -144,27 +129,17 @@ pub async fn invite_new_members( let request = GroupInviteNewRequest { group_invite: Some(invitation), }; - db_rpc.group_invite_new(request).await.map_err(|e| { - Error::InternalServer(format!( - "procedure db rpc service error: group_invite_new {:?}", - e - )) - })?; + db_rpc.group_invite_new(request).await?; let mut chat_rpc = app_state.chat_rpc.clone(); - let msg = bincode::serialize(&members).map_err(|e| Error::InternalServer(e.to_string()))?; + let msg = bincode::serialize(&members)?; // increase the send sequence for sender let (seq, _, _) = app_state.cache.incr_send_seq(&user_id).await?; let request = SendMsgRequest::new_with_group_invite_new(user_id, group_id, seq, msg); - chat_rpc.send_msg(request).await.map_err(|e| { - Error::InternalServer(format!( - "procedure chat rpc service error: send_msg {:?}", - e - )) - })?; + chat_rpc.send_msg(request).await?; Ok(()) } @@ -177,33 +152,26 @@ pub async fn update_group_handler( // send rpc request to update group let mut db_rpc = app_state.db_rpc.clone(); let request = GroupUpdateRequest::new(group_info); - let response = db_rpc.group_update(request).await.map_err(|e| { - Error::InternalServer(format!( - "procedure db rpc service error: group_update {:?}", - e - )) - })?; + let response = db_rpc.group_update(request).await?; - let inner = response.into_inner().group.ok_or(Error::InternalServer( - "group update failed, rpc response is none".to_string(), - ))?; + let inner = response + .into_inner() + .group + .ok_or(Error::internal_with_details( + "update group error, group is none", + ))?; //todo notify the group members, except updater // let mut members = app_state.cache.query_group_members_id(&inner.id).await?; let mut chat_rpc = app_state.chat_rpc.clone(); // notify members, except self - let msg = bincode::serialize(&inner).map_err(|e| Error::InternalServer(e.to_string()))?; + let msg = bincode::serialize(&inner)?; // increase the send sequence for sender let (seq, _, _) = app_state.cache.incr_send_seq(&user_id).await?; let req = SendMsgRequest::new_with_group_update(user_id, inner.id.clone(), seq, msg); - chat_rpc.send_msg(req).await.map_err(|e| { - Error::InternalServer(format!( - "procedure chat rpc service error: send_msg {:?}", - e - )) - })?; + chat_rpc.send_msg(req).await?; Ok(Json(inner)) } @@ -214,15 +182,11 @@ pub async fn remove_member( let req_cloned = req.clone(); let mut db_rpc = app_state.db_rpc.clone(); - db_rpc - .remove_member(req) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + db_rpc.remove_member(req).await?; // send remove message to group members let mut chat_rpc = app_state.chat_rpc.clone(); - let msg = - bincode::serialize(&req_cloned.mem_id).map_err(|e| Error::InternalServer(e.to_string()))?; + let msg = bincode::serialize(&req_cloned.mem_id)?; // increase the send sequence for sender let (seq, _, _) = app_state.cache.incr_send_seq(&req_cloned.user_id).await?; @@ -233,12 +197,7 @@ pub async fn remove_member( seq, msg, ); - chat_rpc.send_msg(request).await.map_err(|e| { - Error::InternalServer(format!( - "procedure chat rpc service error: send_msg {:?}", - e - )) - })?; + chat_rpc.send_msg(request).await?; Ok(()) } @@ -257,23 +216,13 @@ pub async fn delete_group_handler( let mut db_rpc = app_state.db_rpc.clone(); let msg = if group.is_dismiss { let req = GroupDeleteRequest::new(group.group_id.clone(), group.user_id.clone()); - db_rpc.group_delete(req).await.map_err(|e| { - Error::InternalServer(format!( - "procedure db rpc service error: group_delete {:?}", - e - )) - })?; + db_rpc.group_delete(req).await?; MsgType::GroupDismiss } else { // exit group let req = UserAndGroupId::new(group.user_id.clone(), group.group_id.clone()); //todo if the group already dismissed, return success directly - db_rpc.group_member_exit(req.clone()).await.map_err(|e| { - Error::InternalServer(format!( - "procedure db rpc service error: group_member_exit {:?}", - e - )) - })?; + db_rpc.group_member_exit(req.clone()).await?; MsgType::GroupMemberExit }; @@ -283,12 +232,7 @@ pub async fn delete_group_handler( // increase the send sequence for sender let (seq, _, _) = app_state.cache.incr_send_seq(&group.user_id).await?; let ws_req = SendMsgRequest::new_with_group_operation(group.user_id, group.group_id, msg, seq); - chat_rpc.send_msg(ws_req).await.map_err(|e| { - Error::InternalServer(format!( - "procedure chat rpc service error: send_msg {:?}", - e - )) - })?; + chat_rpc.send_msg(ws_req).await?; Ok(()) } diff --git a/api/src/handlers/messages/msg_handlers.rs b/api/src/handlers/messages/msg_handlers.rs index 729c2cc..c627d62 100644 --- a/api/src/handlers/messages/msg_handlers.rs +++ b/api/src/handlers/messages/msg_handlers.rs @@ -51,12 +51,7 @@ pub async fn pull_offline_messages( req.validate()?; // request db rpc - let response = db_rpc.get_msgs(req).await.map_err(|e| { - Error::InternalServer(format!( - "procedure db rpc service error: get_messages {:?}", - e - )) - })?; + let response = db_rpc.get_msgs(req).await?; Ok(Json(response.into_inner().messages)) } @@ -82,11 +77,6 @@ pub async fn del_msg( JsonWithAuthExtractor(req): JsonWithAuthExtractor, ) -> Result<(), Error> { let mut db_rpc = state.db_rpc.clone(); - db_rpc.del_messages(req).await.map_err(|e| { - Error::InternalServer(format!( - "procedure db rpc service error: get_messages {:?}", - e - )) - })?; + db_rpc.del_messages(req).await?; Ok(()) } diff --git a/api/src/handlers/users/mod.rs b/api/src/handlers/users/mod.rs index e82d181..56f6f4e 100644 --- a/api/src/handlers/users/mod.rs +++ b/api/src/handlers/users/mod.rs @@ -47,12 +47,12 @@ impl LoginRequest { pub fn decode(&mut self) -> Result<(), Error> { // base64 decode if self.account.is_empty() || self.password.is_empty() { - return Err(Error::BadRequest("parameter is none".to_string())); + return Err(Error::bad_request("parameter is none")); } let pwd = BASE64_STANDARD_NO_PAD .decode(&self.password) - .map_err(|e| Error::InternalServer(e.to_string()))?; - self.password = String::from_utf8(pwd).map_err(|e| Error::InternalServer(e.to_string()))?; + .map_err(Error::internal)?; + self.password = String::from_utf8(pwd).map_err(Error::internal)?; Ok(()) } } @@ -89,26 +89,28 @@ pub async fn gen_token( &claims, &EncodingKey::from_secret(app_state.jwt_secret.as_bytes()), ) - .map_err(|err| Error::InternalServer(err.to_string()))?; + .map_err(Error::internal)?; + claims.exp += REFRESH_EXPIRES; let refresh_token = encode( &Header::default(), &claims, &EncodingKey::from_secret(app_state.jwt_secret.as_bytes()), ) - .map_err(|err| Error::InternalServer(err.to_string()))?; + .map_err(Error::internal)?; app_state.cache.user_login(&user.account).await?; // get websocket service address // let ws_lb = Arc::get_mut(&mut app_state.ws_lb).unwrap(); - let ws_addr = if let Some(addr) = app_state.ws_lb.get_service().await { - format!("{}://{}/ws", &app_state.ws_config.protocol, addr) - } else { - return Err(Error::InternalServer( - "No websocket service available".to_string(), - )); - }; + let ws_addr = app_state + .ws_lb + .get_service() + .await + .map(|addr| format!("{}://{}/ws", &app_state.ws_config.protocol, addr)) + .ok_or(Error::internal_with_details( + "No websocket service available", + ))?; // query region user.region = match addr.ip() { @@ -130,10 +132,7 @@ pub async fn gen_token( }; let mut db_rpc = app_state.db_rpc.clone(); - let _ = db_rpc - .update_user_region(request) - .await - .map_err(|err| Error::InternalServer(err.message().to_string()))?; + let _ = db_rpc.update_user_region(request).await?; } Ok(Json(Token { @@ -160,12 +159,12 @@ impl ModifyPwdRequest { || self.pwd.is_empty() || self.code.is_empty() { - return Err(Error::BadRequest("parameter is none".to_string())); + return Err(Error::bad_request("parameter is none")); } let pwd = BASE64_STANDARD_NO_PAD .decode(&self.pwd) - .map_err(|e| Error::InternalServer(e.to_string()))?; - self.pwd = String::from_utf8(pwd).map_err(|e| Error::InternalServer(e.to_string()))?; + .map_err(Error::internal)?; + self.pwd = String::from_utf8(pwd).map_err(Error::internal)?; Ok(()) } } diff --git a/api/src/handlers/users/oauth2.rs b/api/src/handlers/users/oauth2.rs index e034afc..46121c8 100644 --- a/api/src/handlers/users/oauth2.rs +++ b/api/src/handlers/users/oauth2.rs @@ -18,7 +18,7 @@ use oauth2::{ TokenResponse, }; use serde::Deserialize; -use tracing::{error, info}; +use tracing::info; use crate::AppState; @@ -80,19 +80,14 @@ pub async fn github_callback( let email = user_emails .into_iter() .find(|item| item.primary) - .ok_or(Error::NotFound)?; + .ok_or(Error::not_found())?; // select user info from db by email let mut db_rpc = state.db_rpc.clone(); let req = GetUserByEmailRequest { email: email.email.clone(), }; - let mut user_info = db_rpc - .get_user_by_email(req) - .await - .map_err(|e| Error::InternalServer(e.to_string()))? - .into_inner() - .user; + let mut user_info = db_rpc.get_user_by_email(req).await?.into_inner().user; // if none, need to get user info from github and register if user_info.is_none() { @@ -133,7 +128,7 @@ async fn get_token_result( .exchange_code(AuthorizationCode::new(code)) .request_async(async_http_client) .await - .map_err(|e| Error::InternalServer(e.to_string())) + .map_err(Error::internal) } async fn download_avatar(url: &str, state: &AppState) -> Result { @@ -182,13 +177,12 @@ async fn register_user(state: &AppState, email: String, access_token: &str) -> R let request = CreateUserRequest { user: Some(user2db), }; - let response = db_rpc.create_user(request).await.map_err(|err| { - error!("create user error: {:?}", err); - Error::InternalServer(err.message().to_string()) - })?; + let response = db_rpc.create_user(request).await?; response .into_inner() .user - .ok_or(Error::InternalServer("Unknown Error".to_string())) + .ok_or(Error::internal_with_details( + "create user failed, user is none", + )) } diff --git a/api/src/handlers/users/user_handlers.rs b/api/src/handlers/users/user_handlers.rs index 45e69af..02183e7 100644 --- a/api/src/handlers/users/user_handlers.rs +++ b/api/src/handlers/users/user_handlers.rs @@ -38,10 +38,7 @@ pub async fn refresh_token( Ok(data) => data, Err(err) => { debug!("token is expired"); - return Err(Error::UnAuthorized( - format!("UnAuthorized Request: {:?}", err), - "/refresh_token".to_string(), - )); + return Err(Error::unauthorized(err, "/refresh_token")); } }; let mut claims = Claims::new(claim.claims.sub.clone()); @@ -53,7 +50,7 @@ pub async fn refresh_token( &claims, &EncodingKey::from_secret(app_state.jwt_secret.as_bytes()), ) - .map_err(|err| Error::InternalServer(err.to_string()))?; + .map_err(Error::internal)?; Ok(token) } @@ -63,12 +60,14 @@ pub async fn create_user( JsonExtractor(new_user): JsonExtractor, ) -> Result, Error> { // verify register code - app_state + let code = app_state .cache .get_register_code(&new_user.email) .await? - .filter(|code| *code == new_user.code) - .ok_or(Error::InvalidRegisterCode)?; + .ok_or(Error::code_expired("in register"))?; + if code != new_user.code { + return Err(Error::code_invalid("in register")); + } // encode the password let salt = utils::generate_salt(); @@ -92,15 +91,12 @@ pub async fn create_user( user: Some(user2db), }; let mut db_rpc = app_state.db_rpc.clone(); - let response = db_rpc.create_user(request).await.map_err(|err| { - error!("create user error: {:?}", err); - Error::InternalServer(err.message().to_string()) - })?; + let response = db_rpc.create_user(request).await?; let user = response .into_inner() .user - .ok_or(Error::InternalServer("Unknown Error".to_string()))?; + .ok_or(Error::internal_with_details("response user is empty"))?; // delete register code from cache app_state.cache.del_register_code(&new_user.email).await?; @@ -115,15 +111,12 @@ pub async fn update_user( // todo need to check the email is registered already let request = UpdateUserRequest { user: Some(user) }; let mut db_rpc = app_state.db_rpc.clone(); - let response = db_rpc.update_user(request).await.map_err(|err| { - error!("create user error: {:?}", err); - Error::InternalServer(err.message().to_string()) - })?; + let response = db_rpc.update_user(request).await?; let user = response .into_inner() .user - .ok_or(Error::InternalServer("Unknown Error".to_string()))?; + .ok_or(Error::internal_with_details("response user is empty"))?; Ok(Json(user)) } @@ -136,11 +129,10 @@ pub async fn get_user_by_id( let request = GetUserRequest { user_id: id }; let user = db_rpc .get_user(request) - .await - .map_err(|err| Error::InternalServer(err.message().to_string()))? + .await? .into_inner() .user - .ok_or(Error::NotFound)?; + .ok_or(Error::not_found())?; Ok(Json(user)) } @@ -150,12 +142,7 @@ pub async fn search_user( ) -> Result>, Error> { let mut db_rpc = app_state.db_rpc.clone(); let request = SearchUserRequest { user_id, pattern }; - let user = db_rpc - .search_user(request) - .await - .map_err(|err| Error::InternalServer(err.message().to_string()))? - .into_inner() - .user; + let user = db_rpc.search_user(request).await?.into_inner().user; Ok(Json(user)) } @@ -181,11 +168,10 @@ pub async fn login( account: login.account, password: login.password, }) - .await - .map_err(|err| Error::InternalServer(err.message().to_string()))? + .await? .into_inner() .user - .ok_or(Error::AccountOrPassword)?; + .ok_or(Error::account_or_pwd())?; gen_token(&app_state, user, addr).await } @@ -202,9 +188,9 @@ pub async fn modify_pwd( .cache .get_register_code(&pwd.email) .await? - .ok_or(Error::BadRequest("code is expired".to_string()))?; + .ok_or(Error::code_expired("code is expired"))?; if code != pwd.code { - return Err(Error::BadRequest("code is invalied".to_string())); + return Err(Error::code_invalid("code is invalid")); } let req = UpdateUserPwdRequest { @@ -213,10 +199,7 @@ pub async fn modify_pwd( }; let mut db_rpc = app_state.db_rpc.clone(); - db_rpc - .update_user_pwd(req) - .await - .map_err(|err| Error::InternalServer(err.message().to_string()))?; + db_rpc.update_user_pwd(req).await?; Ok(()) } @@ -230,12 +213,11 @@ pub async fn send_email( JsonExtractor(email): JsonExtractor, ) -> Result<(), Error> { if email.email.is_empty() { - return Err(Error::BadRequest("parameter is none".to_string())); + return Err(Error::bad_request("parameter is none".to_string())); } // get email template engine tera - let tera = Tera::new(&state.mail_config.temp_path) - .map_err(|e| Error::InternalServer(e.to_string()))?; + let tera = Tera::new(&state.mail_config.temp_path).map_err(Error::internal)?; // generate random number(validate code) let mut rng = rand::thread_rng(); let num: u32 = rng.gen_range(100_000..1_000_000); @@ -245,21 +227,12 @@ pub async fn send_email( context.insert("numbers", &num.to_string()); let content = tera .render(&state.mail_config.temp_file, &context) - .map_err(|e| Error::InternalServer(e.to_string()))?; + .map_err(Error::internal)?; // save it to redis; expire time 5 minutes let msg = Message::builder() - .from( - state - .mail_config - .account - .parse() - .map_err(|_| Error::InternalServer("email parse failed".to_string()))?, - ) - .to(email - .email - .parse() - .map_err(|_| Error::InternalServer("user email parse failed".to_string()))?) + .from(state.mail_config.account.parse().map_err(Error::internal)?) + .to(email.email.parse().map_err(Error::internal)?) .subject("Verify Login Code") .header(ContentType::TEXT_PLAIN) .multipart( @@ -269,20 +242,18 @@ pub async fn send_email( .body(content), ), ) - .map_err(|err| Error::InternalServer(err.to_string()))?; + .map_err(Error::internal)?; let creds = Credentials::new(state.mail_config.account, state.mail_config.password); // Open a remote connection to mail let mailer = SmtpTransport::relay(&state.mail_config.server) - .map_err(|err| Error::InternalServer(err.to_string()))? + .map_err(Error::internal)? .credentials(creds) .build(); // Send the email - mailer - .send(&msg) - .map_err(|e| Error::InternalServer(e.to_string()))?; + mailer.send(&msg).map_err(Error::internal)?; tokio::spawn(async move { if let Err(e) = state .cache diff --git a/consumer/src/lib.rs b/consumer/src/lib.rs index c79810b..a40e83a 100644 --- a/consumer/src/lib.rs +++ b/consumer/src/lib.rs @@ -110,8 +110,7 @@ impl ConsumerService { let mut msg: Msg = serde_json::from_str(payload)?; - let mt = - MsgType::try_from(msg.msg_type).map_err(|e| Error::InternalServer(e.to_string()))?; + let mt = MsgType::try_from(msg.msg_type).map_err(Error::internal)?; // handle message read type if mt == MsgType::Read { @@ -175,7 +174,7 @@ impl ConsumerService { futures::future::try_join_all(tasks) .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + .map_err(Error::internal)?; Ok(()) } @@ -250,8 +249,7 @@ impl ConsumerService { .save_send_max_seq(SaveMaxSeqRequest { user_id: user_id.to_string(), }) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + .await?; } Ok(()) } @@ -264,23 +262,20 @@ impl ConsumerService { .save_max_seq(SaveMaxSeqRequest { user_id: user_id.to_string(), }) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + .await?; } Ok(cur_seq) } async fn handle_msg_read(&self, msg: Msg) -> Result<(), Error> { - let data = - bincode::deserialize(&msg.content).map_err(|e| Error::InternalServer(e.to_string()))?; + let data = bincode::deserialize(&msg.content)?; let mut db_rpc = self.db_rpc.clone(); db_rpc .read_msg(MsgReadReq { msg_read: Some(data), }) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + .await?; Ok(()) } @@ -313,8 +308,7 @@ impl ConsumerService { .remove_group_member_id(&msg.receiver_id, &msg.send_id) .await?; } else if msg.msg_type == MsgType::GroupRemoveMember as i32 { - let data: Vec = bincode::deserialize(&msg.content) - .map_err(|e| Error::InternalServer(e.to_string()))?; + let data: Vec = bincode::deserialize(&msg.content)?; let member_ids_ref: Vec<&str> = data.iter().map(AsRef::as_ref).collect(); self.cache @@ -350,17 +344,11 @@ impl ConsumerService { match msg_type { MsgType2::Single => { let request = SaveMessageRequest::new(msg, need_to_history); - db_rpc - .save_message(request) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + db_rpc.save_message(request).await?; } MsgType2::Group => { let request = SaveGroupMsgRequest::new(msg, need_to_history, members); - db_rpc - .save_group_message(request) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + db_rpc.save_group_message(request).await?; } } @@ -373,8 +361,7 @@ impl ConsumerService { ) -> Result<(), Error> { pusher .push_single_msg(SendMsgRequest { message: Some(msg) }) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + .await?; Ok(()) } @@ -388,8 +375,7 @@ impl ConsumerService { message: Some(msg), members, }) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + .await?; Ok(()) } @@ -400,25 +386,20 @@ impl ConsumerService { group_id: group_id.to_string(), }; let mut db_rpc = self.db_rpc.clone(); - match db_rpc.group_members_id(request).await { - Ok(resp) => { - let members_id = resp.into_inner().members_id; - - // save it to cache - if let Err(e) = self - .cache - .save_group_members_id(group_id, members_id.clone()) - .await - { - error!("failed to save group members id to cache: {:?}", e); - } - - Ok(members_id) - } - Err(e) => { - error!("failed to query group members id from db: {:?}", e); - Err(Error::InternalServer(e.to_string())) + let resp = db_rpc.group_members_id(request).await?; + { + let members_id = resp.into_inner().members_id; + + // save it to cache + if let Err(e) = self + .cache + .save_group_members_id(group_id, members_id.clone()) + .await + { + error!("failed to save group members id to cache: {:?}", e); } + + Ok(members_id) } } } diff --git a/db/src/database/mongodb/message.rs b/db/src/database/mongodb/message.rs index f69fb86..20590be 100644 --- a/db/src/database/mongodb/message.rs +++ b/db/src/database/mongodb/message.rs @@ -6,7 +6,6 @@ use mongodb::{ }; use tokio::sync::mpsc; use tonic::codegen::tokio_stream::StreamExt; -use tracing::error; use tracing::log::debug; use abi::config::Config; @@ -170,17 +169,10 @@ impl MsgRecBoxRepo for MsgBox { let mut cursor = self.mb.find(query, Some(option)).await?; let mut messages = Vec::with_capacity((end - start) as usize); while let Some(result) = cursor.next().await { - match result { - Ok(doc) => { - let msg = Msg::try_from(doc)?; - messages.push(msg) - } - Err(e) => { - error!("{:?}", e); - return Err(Error::MongoDbOperateError(e)); - } - } + let msg = Msg::try_from(result?)?; + messages.push(msg) } + Ok(messages) } @@ -232,20 +224,12 @@ impl MsgRecBoxRepo for MsgBox { let mut messages = Vec::with_capacity((len) as usize); while let Some(result) = cursor.next().await { - match result { - Ok(doc) => { - let mut msg = Msg::try_from(doc)?; - // set seq to 0 if the message is sent by the user - if user_id == msg.send_id { - msg.seq = 0; - } - messages.push(msg) - } - Err(e) => { - error!("{:?}", e); - return Err(Error::MongoDbOperateError(e)); - } + let mut msg = Msg::try_from(result?)?; + // set seq to 0 if the message is sent by the user + if user_id == msg.send_id { + msg.seq = 0; } + messages.push(msg) } Ok(messages) } diff --git a/db/src/database/postgres/group.rs b/db/src/database/postgres/group.rs index fa879b7..c034f18 100644 --- a/db/src/database/postgres/group.rs +++ b/db/src/database/postgres/group.rs @@ -79,7 +79,7 @@ impl GroupStoreRepo for PostgresGroup { .await?; if !user_belongs_to_group.0 { - return Err(Error::NotFound); + return Err(Error::db_not_found("user not belongs to the group")); } let members = @@ -163,7 +163,7 @@ impl GroupStoreRepo for PostgresGroup { .await?; if !user_belongs_to_group.0 { - return Err(Error::NotFound); + return Err(Error::db_not_found("user not belongs to the group")); } // insert new members diff --git a/db/src/database/postgres/user.rs b/db/src/database/postgres/user.rs index effcc41..bb02461 100644 --- a/db/src/database/postgres/user.rs +++ b/db/src/database/postgres/user.rs @@ -151,8 +151,9 @@ impl UserRepo for PostgresUser { } let mut user = user.unwrap(); - let parsed_hash = - PasswordHash::new(&user.password).map_err(|e| Error::InternalServer(e.to_string()))?; + let parsed_hash = PasswordHash::new(&user.password) + .map_err(|e| Error::internal_with_details(e.to_string()))?; + let is_valid = Argon2::default() .verify_password(password.as_bytes(), &parsed_hash) .is_ok(); diff --git a/db/src/rpc/mod.rs b/db/src/rpc/mod.rs index 05d88f5..6762b8e 100644 --- a/db/src/rpc/mod.rs +++ b/db/src/rpc/mod.rs @@ -102,7 +102,7 @@ impl DbRpcService { // wait all tasks futures::future::try_join_all(tasks) .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + .map_err(Error::internal)?; Ok(()) } @@ -161,8 +161,8 @@ impl DbRpcService { }); // wait all tasks complete - let (db_result, msg_rec_box_result) = tokio::try_join!(db_task, msg_rec_box_task) - .map_err(|err| Error::InternalServer(err.to_string()))?; + let (db_result, msg_rec_box_result) = + tokio::try_join!(db_task, msg_rec_box_task).map_err(Error::internal)?; db_result?; msg_rec_box_result?; diff --git a/oss/src/client.rs b/oss/src/client.rs index 034d265..46c3e98 100644 --- a/oss/src/client.rs +++ b/oss/src/client.rs @@ -59,14 +59,14 @@ impl S3Client { if e.raw().status().as_u16() == 404 { Ok(false) } else { - Err(Error::InternalServer( - "check_bucket_exists error".to_string(), + Err(Error::internal_with_details( + "check avatar_bucket exists error", )) } } Err(e) => { error!("check_bucket_exists error: {:?}", e); - Err(Error::InternalServer(e.to_string())) + Err(Error::internal_with_details(e.to_string())) } } } @@ -84,14 +84,14 @@ impl S3Client { if e.raw().status().as_u16() == 404 { Ok(false) } else { - Err(Error::InternalServer( - "check avatar_bucket exists error".to_string(), + Err(Error::internal_with_details( + "check avatar_bucket exists error", )) } } Err(e) => { error!("check avatar_bucket exists error: {:?}", e); - Err(Error::InternalServer(e.to_string())) + Err(Error::internal_with_details(e.to_string())) } } } @@ -114,8 +114,7 @@ impl S3Client { .create_bucket() .bucket(&self.bucket) .send() - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + .await?; } if !self.check_avatar_bucket_exits().await? { @@ -123,8 +122,7 @@ impl S3Client { .create_bucket() .bucket(&self.avatar_bucket) .send() - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + .await?; } Ok(()) } @@ -197,11 +195,7 @@ impl S3Client { .key(key) .body(content.into()) .send() - .await - .map_err(|e| { - error!("{:?}", e); - Error::InternalServer(e.to_string()) - })?; + .await?; Ok(()) } @@ -212,14 +206,9 @@ impl S3Client { .bucket(bucket) .key(key) .send() - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + .await?; - let data = resp - .body - .collect() - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + let data = resp.body.collect().await.map_err(Error::internal)?; Ok(data.into_bytes()) } @@ -231,8 +220,7 @@ impl S3Client { .bucket(bucket) .key(key) .send() - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + .await?; Ok(()) } diff --git a/utils/src/lib.rs b/utils/src/lib.rs index 0152502..99fa715 100644 --- a/utils/src/lib.rs +++ b/utils/src/lib.rs @@ -33,11 +33,9 @@ pub mod sqlx_tester; // get host name pub fn get_host_name() -> Result { let hostname = hostname::get()?; - let hostname = hostname.into_string().map_err(|_| { - Error::InternalServer(String::from( - "get hostname error: OsString into String Failed", - )) - })?; + let hostname = hostname + .into_string() + .map_err(|_| Error::internal_with_details("get host name failed"))?; Ok(hostname) } @@ -58,7 +56,7 @@ pub async fn get_rpc_channel_by_name( break; } if i == 5 { - return Err(Error::ServiceNotFound(String::from(name))); + return Err(Error::service_not_found(name)); } } } @@ -84,7 +82,7 @@ pub fn hash_password(password: &[u8], salt: &str) -> Result { // Hash password to PHC string ($argon2id$v=19$...) Ok(argon2 .hash_password(password, &SaltString::from_b64(salt).unwrap()) - .map_err(|e| Error::InternalServer(e.to_string()))? + .map_err(|e| Error::internal_with_details(e.to_string()))? .to_string()) } @@ -184,9 +182,7 @@ pub async fn get_chan_( .connect_timeout(Duration::from_secs(5)) .build() .await - .map_err(|_| { - Error::InternalServer("Connect to service register center failed".to_string()) - })?; + .map_err(|e| Error::internal_with_details(e.to_string()))?; tokio::spawn(async move { let mut stream = match client.subscribe(name).await { @@ -249,12 +245,9 @@ pub async fn register_service(config: &Config, com: Component) -> Result<(), Err "{}://{}:{}", config.service_center.protocol, config.service_center.host, config.service_center.port ); - let endpoint = Endpoint::from_shared(addr) - .map_err(|e| Error::TonicError(e.to_string()))? + let endpoint = Endpoint::from_shared(addr)? .connect_timeout(Duration::from_secs(config.service_center.timeout)); - let mut client = ServiceRegistryClient::connect(endpoint) - .await - .map_err(|e| Error::TonicError(e.to_string()))?; + let mut client = ServiceRegistryClient::connect(endpoint).await?; let (scheme, name, host, port, tags) = match com { abi::config::Component::Chat => { diff --git a/utils/src/service_discovery/tonic_service_discovery.rs b/utils/src/service_discovery/tonic_service_discovery.rs index 3a2f292..7c0bdef 100644 --- a/utils/src/service_discovery/tonic_service_discovery.rs +++ b/utils/src/service_discovery/tonic_service_discovery.rs @@ -62,10 +62,7 @@ impl DynamicServiceDiscovery { let x = self.service_center.fetch().await?; let change_set = self.change_set(&x).await; for change in change_set { - self.sender - .send(change) - .await - .map_err(|e| Error::InternalServer(e.to_string()))?; + self.sender.send(change).await.map_err(Error::internal)?; } self.services = x; Ok(()) diff --git a/utils/src/service_register_center/consul/mod.rs b/utils/src/service_register_center/consul/mod.rs index 83990e3..ad93610 100644 --- a/utils/src/service_register_center/consul/mod.rs +++ b/utils/src/service_register_center/consul/mod.rs @@ -66,7 +66,7 @@ impl ServiceRegister for Consul { let response = self.client.put(&url).json(®istration).send().await?; debug!("register service: {:?} to consul{url}", registration); if !response.status().is_success() { - return Err(Error::InternalServer( + return Err(Error::internal_with_details( response.text().await.unwrap_or_default(), )); } @@ -89,7 +89,7 @@ impl ServiceRegister for Consul { let url = self.api_url(&format!("service/deregister/{}", service_id)); let response = self.client.put(url).send().await?; if !response.status().is_success() { - return Err(Error::InternalServer( + return Err(Error::internal_with_details( response.text().await.unwrap_or_default(), )); } diff --git a/ws/src/manager.rs b/ws/src/manager.rs index 7b115db..f63785b 100644 --- a/ws/src/manager.rs +++ b/ws/src/manager.rs @@ -218,6 +218,9 @@ impl Manager { } pub async fn broadcast(&self, msg: Msg) -> Result<(), Error> { - self.tx.send(msg).await.map_err(|_| Error::BroadCastError) + self.tx + .send(msg) + .await + .map_err(|e| Error::broadcast(Box::new(e))) } } diff --git a/ws/src/ws_server.rs b/ws/src/ws_server.rs index b2d0cc9..65298c2 100644 --- a/ws/src/ws_server.rs +++ b/ws/src/ws_server.rs @@ -137,7 +137,7 @@ impl WsServer { &DecodingKey::from_secret(jwt_secret.as_bytes()), &Validation::default(), ) { - return Err(Error::UnAuthorized(err.to_string(), "/ws".to_string())); + return Err(Error::unauthorized(err, "/ws")); } Ok(()) } From f1be9eaa882df2313cf8fc74593438a90d0e5ead Mon Sep 17 00:00:00 2001 From: Xu_Mj <40650924+Xu-Mj@users.noreply.github.com> Date: Sun, 28 Jul 2024 09:50:19 +0800 Subject: [PATCH 2/7] feat: use bad_request func --- abi/src/types/msg.rs | 72 ++++++-------------------------------------- 1 file changed, 9 insertions(+), 63 deletions(-) diff --git a/abi/src/types/msg.rs b/abi/src/types/msg.rs index 87bc9ed..acca2cb 100644 --- a/abi/src/types/msg.rs +++ b/abi/src/types/msg.rs @@ -1,7 +1,7 @@ use mongodb::bson::Document; use tonic::Status; -use crate::errors::{Error, ErrorKind}; +use crate::errors::Error; use crate::message::{ GetDbMessagesRequest, GetDbMsgRequest, GroupMemSeq, Msg, MsgResponse, MsgType, SaveGroupMsgRequest, SaveMessageRequest, SendMsgRequest, UserAndGroupId, @@ -205,25 +205,16 @@ impl UserAndGroupId { impl GetDbMsgRequest { pub fn validate(&self) -> Result<(), Error> { if self.user_id.is_empty() { - return Err(Error::with_details( - ErrorKind::BadRequest, - "user_id is empty", - )); + return Err(Error::bad_request("user_id is empty")); } if self.start < 0 { - return Err(Error::with_details( - ErrorKind::BadRequest, - "start is invalid".to_string(), - )); + return Err(Error::bad_request("start is invalid")); } if self.end < 0 { - return Err(Error::with_details(ErrorKind::BadRequest, "end is invalid")); + return Err(Error::bad_request("end is invalid")); } if self.end < self.start { - return Err(Error::with_details( - ErrorKind::BadRequest, - "start is greater than end", - )); + return Err(Error::bad_request("start is greater than end")); } Ok(()) } @@ -232,66 +223,21 @@ impl GetDbMsgRequest { impl GetDbMessagesRequest { pub fn validate(&self) -> Result<(), Error> { if self.user_id.is_empty() { - return Err(Error::with_details( - ErrorKind::BadRequest, - "user_id is empty", - )); + return Err(Error::bad_request("user_id is empty")); } if self.start < 0 { - return Err(Error::with_details( - ErrorKind::BadRequest, - "start is invalid", - )); + return Err(Error::bad_request("start is invalid")); } if self.end < 0 { - return Err(Error::with_details(ErrorKind::BadRequest, "end is invalid")); + return Err(Error::bad_request("end is invalid")); } if self.end < self.start { - return Err(Error::with_details( - ErrorKind::BadRequest, - "start is greater than end", - )); + return Err(Error::bad_request("start is greater than end")); } Ok(()) } } -// impl GetDbMsgRequest { -// pub fn validate(&self) -> Result<(), Error> { -// if self.user_id.is_empty() { -// return Err(Error::BadRequest("user_id is empty".to_string())); -// } -// if self.start < 0 { -// return Err(Error::BadRequest("start is invalid".to_string())); -// } -// if self.end < 0 { -// return Err(Error::BadRequest("end is invalid".to_string())); -// } -// if self.end < self.start { -// return Err(Error::BadRequest("start is greater than end".to_string())); -// } -// Ok(()) -// } -// } - -// impl GetDbMessagesRequest { -// pub fn validate(&self) -> Result<(), Error> { -// if self.user_id.is_empty() { -// return Err(Error::BadRequest("user_id is empty".to_string())); -// } -// if self.start < 0 { -// return Err(Error::BadRequest("start is invalid".to_string())); -// } -// if self.end < 0 { -// return Err(Error::BadRequest("end is invalid".to_string())); -// } -// if self.end < self.start { -// return Err(Error::BadRequest("start is greater than end".to_string())); -// } -// Ok(()) -// } -// } - impl SaveMessageRequest { pub fn new(msg: Msg, need_to_history: bool) -> Self { Self { From c1aaca306a2f956606f24e7b52e5251d40919564 Mon Sep 17 00:00:00 2001 From: Xu_Mj <40650924+Xu-Mj@users.noreply.github.com> Date: Sun, 28 Jul 2024 10:00:24 +0800 Subject: [PATCH 3/7] feat: delete deprecated comment --- abi/src/errors/mod.rs | 325 ------------------ api/src/api_utils/custom_extract/auth.rs | 41 +-- .../custom_extract/json_extractor.rs | 13 +- .../custom_extract/path_extractor.rs | 41 +-- 4 files changed, 6 insertions(+), 414 deletions(-) diff --git a/abi/src/errors/mod.rs b/abi/src/errors/mod.rs index 4e0eaf0..d2d5dd0 100644 --- a/abi/src/errors/mod.rs +++ b/abi/src/errors/mod.rs @@ -1,328 +1,3 @@ -// use axum::http::StatusCode; -// use axum::response::{IntoResponse, Response}; -// use axum::Json; -// use mongodb::bson::document::ValueAccessError; -// use serde_json::json; -// use tonic::{Code, Status}; -// use tracing::error; - -// type Message = String; -// type Location = String; -// type Path = String; - -// pub struct Error -// where -// T: std::error::Error, -// { -// kind: ErrorKind, -// error: Option, -// details: Option, -// } - -// #[derive(Debug)] -// pub enum ErrorKind { -// // #[error("unknown errors")] -// UnknownError, - -// // #[error("database errors{0}")] -// DbError/* (sqlx::Error) */, - -// // #[error("config file read errors")] -// ConfigReadError, - -// // #[error("config parse errors")] -// ConfigParseError/* (serde_yaml::Error) */, - -// #[error("Not found by the given condition")] -// NotFound, - -// #[error("broadcast errors")] -// BroadCastError, - -// // 500 -// #[error("internal server errors")] -// InternalServer(Message), - -// // 400 -// #[error("body parsing errors")] -// BodyParsing(Message, Path), - -// #[error("path parsing errors{0}")] -// PathParsing(Message, Option), - -// #[error("unauthorized request{0}, path: {1}")] -// UnAuthorized(Message, Path), - -// #[error("parse error: {0}")] -// ParseError(Message), - -// #[error("tonic error: {0}")] -// TonicError(Message), - -// #[error("mongodb value access error: {0}")] -// MongoDbValueAccessError(ValueAccessError), - -// #[error("mongodb bson serde error: {0}")] -// MongoDbBsonSerError(mongodb::bson::ser::Error), - -// #[error("mongodb value access error: {0}")] -// MongoDbOperateError(mongodb::error::Error), - -// #[error("redis error: {0}")] -// RedisError(redis::RedisError), - -// #[error("io error: {0}")] -// IOError(std::io::Error), - -// #[error("reqwest error: {0}")] -// ReqwestError(reqwest::Error), - -// #[error("service not found: {0}")] -// ServiceNotFound(String), - -// #[error("invalid register code ")] -// InvalidRegisterCode, - -// #[error("bad request: {0}")] -// BadRequest(String), - -// #[error("account or password error")] -// AccountOrPassword, -// } - -// impl From for Error { -// fn from(value: std::io::Error) -> Self { -// Self::IOError(value) -// } -// } - -// impl From for Error { -// fn from(value: redis::RedisError) -> Self { -// Self::RedisError(value) -// } -// } - -// impl From for Error { -// fn from(value: serde_yaml::Error) -> Self { -// Self::ConfigParseError(value) -// } -// } - -// impl From for Error { -// fn from(value: reqwest::Error) -> Self { -// Self::ReqwestError(value) -// } -// } - -// impl From for Error { -// fn from(value: ValueAccessError) -> Self { -// Self::MongoDbValueAccessError(value) -// } -// } - -// impl From for Error { -// fn from(value: mongodb::bson::ser::Error) -> Self { -// Self::MongoDbBsonSerError(value) -// } -// } - -// impl From for Error { -// fn from(value: mongodb::error::Error) -> Self { -// Self::MongoDbOperateError(value) -// } -// } - -// // convert sqlx::Error to Error::ConfilictReservation -// impl From for Error { -// fn from(e: sqlx::Error) -> Self { -// Error::DbError(e) -// } -// } - -// impl From for Error { -// fn from(value: serde_json::Error) -> Self { -// Self::ParseError(value.to_string()) -// } -// } - -// // convert abi::Error to tonic::Status -// impl From for Status { -// fn from(e: Error) -> Self { -// // log the error details -// error!("{:?}", e); -// match e { -// Error::DbError(e) => Status::internal(e.to_string()), -// Error::UnknownError => Status::unknown(e.to_string()), -// Error::ConfigReadError | Error::ConfigParseError(_) => Status::internal(e.to_string()), -// Error::NotFound => Status::not_found(e.to_string()), -// Error::InternalServer(msg) => Status::internal(msg), -// Error::BodyParsing(_, _) => Status::invalid_argument(e.to_string()), -// Error::PathParsing(_, _) => Status::invalid_argument(e.to_string()), -// Error::UnAuthorized(_, _) => Status::unauthenticated(e.to_string()), -// Error::BroadCastError => Status::internal(e.to_string()), -// Error::ParseError(e) => Status::internal(e.to_string()), -// Error::TonicError(e) => Status::internal(e.to_string()), -// Error::MongoDbValueAccessError(e) => Status::internal(e.to_string()), -// Error::MongoDbOperateError(e) => Status::internal(e.to_string()), -// Error::MongoDbBsonSerError(e) => Status::internal(e.to_string()), -// Error::RedisError(_) => Status::internal(e.to_string()), -// Error::ReqwestError(_) => Status::internal(e.to_string()), -// Error::IOError(_) => Status::internal(e.to_string()), -// Error::ServiceNotFound(_) => Status::internal(e.to_string()), -// Error::InvalidRegisterCode => Status::invalid_argument(e.to_string()), -// Error::BadRequest(_) => Status::invalid_argument(e.to_string()), -// Error::AccountOrPassword => Status::invalid_argument(e.to_string()), -// } -// } -// } - -// impl From for Error { -// fn from(status: Status) -> Self { -// let message = status.message().to_string(); -// match status.code() { -// Code::Ok => Error::UnknownError, // 根据需要处理 Ok 状态 -// Code::Cancelled => Error::InternalServer(message), -// Code::Unknown => Error::InternalServer(message), -// Code::InvalidArgument => Error::BodyParsing(message, Path::default()), -// Code::DeadlineExceeded => Error::InternalServer(message), -// Code::NotFound => Error::NotFound, -// Code::AlreadyExists => Error::InternalServer(message), -// Code::PermissionDenied => Error::InternalServer(message), -// Code::ResourceExhausted => Error::InternalServer(message), -// Code::FailedPrecondition => Error::InternalServer(message), -// Code::Aborted => Error::InternalServer(message), -// Code::OutOfRange => Error::InternalServer(message), -// Code::Unimplemented => Error::InternalServer(message), -// Code::Internal => Error::InternalServer(message), -// Code::Unavailable => Error::InternalServer(message), -// Code::DataLoss => Error::InternalServer(message), -// Code::Unauthenticated => Error::UnAuthorized(message, Path::default()), -// } -// } -// } - -// impl IntoResponse for Error { -// fn into_response(self) -> Response { -// let status_code = match self { -// Error::UnknownError => StatusCode::INTERNAL_SERVER_ERROR, -// Error::BodyParsing(_, _) => StatusCode::BAD_REQUEST, -// Error::PathParsing(_, _) => StatusCode::BAD_REQUEST, -// Error::UnAuthorized(_, _) => StatusCode::UNAUTHORIZED, -// Error::NotFound => StatusCode::NOT_FOUND, -// Error::DbError(_) => StatusCode::INTERNAL_SERVER_ERROR, -// Error::ParseError(_) | Error::ConfigReadError => StatusCode::INTERNAL_SERVER_ERROR, -// Error::ConfigParseError(_) => StatusCode::INTERNAL_SERVER_ERROR, -// Error::TonicError(_) => StatusCode::INTERNAL_SERVER_ERROR, -// Error::MongoDbValueAccessError(_) => StatusCode::INTERNAL_SERVER_ERROR, -// Error::MongoDbOperateError(_) => StatusCode::INTERNAL_SERVER_ERROR, -// Error::MongoDbBsonSerError(_) => StatusCode::INTERNAL_SERVER_ERROR, -// Error::RedisError(_) => StatusCode::INTERNAL_SERVER_ERROR, -// Error::ReqwestError(_) => StatusCode::INTERNAL_SERVER_ERROR, -// Error::IOError(_) => StatusCode::INTERNAL_SERVER_ERROR, -// Error::ServiceNotFound(_) => StatusCode::INTERNAL_SERVER_ERROR, -// Error::InternalServer(_) => StatusCode::INTERNAL_SERVER_ERROR, -// Error::BroadCastError => StatusCode::INTERNAL_SERVER_ERROR, -// Error::InvalidRegisterCode => StatusCode::BAD_REQUEST, -// Error::BadRequest(_) => StatusCode::BAD_REQUEST, -// Error::AccountOrPassword => StatusCode::UNAUTHORIZED, -// }; -// let msg = self.to_string(); - -// (status_code, Json(json!({"error": msg}))).into_response() -// } -// } -// impl IntoResponse for Error { -// fn into_response(self) -> Response { -// let (status, msg) = match self { -// Error::UnknownError => ( -// StatusCode::INTERNAL_SERVER_ERROR, -// "UNKNOWN ERROR".to_string(), -// ), -// Error::BodyParsing(msg, path) => ( -// StatusCode::BAD_REQUEST, -// format!("Bad Request errors: {{ message: {}, path: {}}}", msg, path), -// ), -// Error::PathParsing(msg, location) => { -// let mut msg = format!("Bad Request errors: {}", msg); -// if location.is_some() { -// msg = format!("Bad Request errors: in {} : {}", location.unwrap(), msg); -// } -// (StatusCode::BAD_REQUEST, msg) -// } -// Error::UnAuthorized(msg, path) => ( -// StatusCode::UNAUTHORIZED, -// format!("Bad Request errors: {{ message: {}, path: {}}}", msg, path), -// ), -// Error::NotFound => (StatusCode::NOT_FOUND, "NOT FOUND".to_string()), -// Error::DbError(e) => ( -// StatusCode::INTERNAL_SERVER_ERROR, -// format!("INTERNAL SERVER ERROR {:?}", e), -// ), -// Error::ParseError(_) | Error::ConfigReadError => ( -// StatusCode::INTERNAL_SERVER_ERROR, -// "INTERNAL SERVER ERROR ".to_string(), -// ), -// Error::ConfigParseError(e) => ( -// StatusCode::INTERNAL_SERVER_ERROR, -// format!("INTERNAL SERVER ERROR {e}"), -// ), -// Error::TonicError(e) => ( -// StatusCode::INTERNAL_SERVER_ERROR, -// format!("INTERNAL SERVER ERROR {e}"), -// ), -// Error::MongoDbValueAccessError(e) => ( -// StatusCode::INTERNAL_SERVER_ERROR, -// format!("INTERNAL SERVER ERROR {:?}", e), -// ), -// Error::MongoDbOperateError(e) => ( -// StatusCode::INTERNAL_SERVER_ERROR, -// format!("INTERNAL SERVER ERROR {e}"), -// ), -// Error::MongoDbBsonSerError(e) => ( -// StatusCode::INTERNAL_SERVER_ERROR, -// format!("INTERNAL SERVER ERROR {e}"), -// ), -// Error::RedisError(e) => ( -// StatusCode::INTERNAL_SERVER_ERROR, -// format!("INTERNAL SERVER ERROR {:?}", e), -// ), -// Error::ReqwestError(e) => ( -// StatusCode::INTERNAL_SERVER_ERROR, -// format!("INTERNAL SERVER ERROR {e}"), -// ), -// Error::IOError(e) => ( -// StatusCode::INTERNAL_SERVER_ERROR, -// format!("INTERNAL SERVER ERROR {e}"), -// ), -// Error::ServiceNotFound(e) => ( -// StatusCode::INTERNAL_SERVER_ERROR, -// format!("INTERNAL SERVER ERROR {e}"), -// ), -// Error::InternalServer(e) => ( -// StatusCode::INTERNAL_SERVER_ERROR, -// format!("INTERNAL SERVER ERROR {e}"), -// ), -// Error::BroadCastError => ( -// StatusCode::INTERNAL_SERVER_ERROR, -// "BROADCAST ERROR".to_string(), -// ), -// Error::InvalidRegisterCode => { -// (StatusCode::BAD_REQUEST, "INVALID REGISTER CODE".to_string()) -// } -// Error::BadRequest(msg) => ( -// StatusCode::BAD_REQUEST, -// format!("Bad Request errors: {msg}"), -// ), -// Error::AccountOrPassword => ( -// StatusCode::UNAUTHORIZED, -// "INVALID ACCOUNT OR PASSWORD".to_string(), -// ), -// }; -// error!("http request api error: {:?}", msg); -// (status, Json(json!({"message":msg}))).into_response() -// } -// } - use aws_sdk_s3::error::SdkError; use axum::{ http::StatusCode, diff --git a/api/src/api_utils/custom_extract/auth.rs b/api/src/api_utils/custom_extract/auth.rs index 41f4e2c..e2a7129 100644 --- a/api/src/api_utils/custom_extract/auth.rs +++ b/api/src/api_utils/custom_extract/auth.rs @@ -130,46 +130,7 @@ where Err(rejection) => { let (status, body) = match rejection { PathRejection::FailedToDeserializePathParams(inner) => { - let status = StatusCode::BAD_REQUEST; - - // let kind = inner.into_kind(); - let body = Error::path_parsing(inner); - // let body = match &kind { - // ErrorKind::WrongNumberOfParameters { .. } => { - // Error::PathParsing(kind.to_string(), None) - // } - - // ErrorKind::ParseErrorAtKey { key, .. } => { - // Error::PathParsing(kind.to_string(), Some(key.clone())) - // } - - // ErrorKind::ParseErrorAtIndex { index, .. } => { - // Error::PathParsing(kind.to_string(), Some(index.to_string())) - // } - - // ErrorKind::ParseError { .. } => { - // Error::PathParsing(kind.to_string(), None) - // } - - // ErrorKind::InvalidUtf8InPathParam { key } => { - // Error::PathParsing(kind.to_string(), Some(key.clone())) - // } - - // ErrorKind::UnsupportedType { .. } => { - // // these errors are caused by the programmer using an unsupported type - // // (such as nested maps) so respond with `500` instead - // status = StatusCode::INTERNAL_SERVER_ERROR; - // Error::InternalServer(kind.to_string()) - // } - - // ErrorKind::Message(msg) => Error::PathParsing(msg.clone(), None), - // _ => Error::PathParsing( - // format!("Unhandled deserialization errors: {kind}"), - // None, - // ), - // }; - - (status, body) + (StatusCode::BAD_REQUEST, Error::path_parsing(inner)) } PathRejection::MissingPathParams(error) => ( StatusCode::INTERNAL_SERVER_ERROR, diff --git a/api/src/api_utils/custom_extract/json_extractor.rs b/api/src/api_utils/custom_extract/json_extractor.rs index b6d2fa7..936f9fe 100644 --- a/api/src/api_utils/custom_extract/json_extractor.rs +++ b/api/src/api_utils/custom_extract/json_extractor.rs @@ -34,15 +34,10 @@ where match axum::Json::::from_request(req, state).await { Ok(value) => Ok(Self(value.0)), // convert the errors from `axum::Json` into whatever we want - Err(rejection) => { - // let mut ph = String::new(); - // if path.is_some() { - // ph = path.unwrap(); - // } - let app_err = Error::body_parsing(rejection.body_text()); - - Err((rejection.status(), app_err)) - } + Err(rejection) => Err(( + rejection.status(), + Error::body_parsing(rejection.body_text()), + )), } } } diff --git a/api/src/api_utils/custom_extract/path_extractor.rs b/api/src/api_utils/custom_extract/path_extractor.rs index 8f458d8..1eeb1ef 100644 --- a/api/src/api_utils/custom_extract/path_extractor.rs +++ b/api/src/api_utils/custom_extract/path_extractor.rs @@ -24,46 +24,7 @@ where Err(rejection) => { let (status, body) = match rejection { PathRejection::FailedToDeserializePathParams(inner) => { - let status = StatusCode::BAD_REQUEST; - let body = Error::path_parsing(inner); - - // let kind = inner.into_kind(); - // let body = match &kind { - // ErrorKind::WrongNumberOfParameters { .. } => { - // Error::PathParsing(kind.to_string(), None) - // } - - // ErrorKind::ParseErrorAtKey { key, .. } => { - // Error::PathParsing(kind.to_string(), Some(key.clone())) - // } - - // ErrorKind::ParseErrorAtIndex { index, .. } => { - // Error::PathParsing(kind.to_string(), Some(index.to_string())) - // } - - // ErrorKind::ParseError { .. } => { - // Error::PathParsing(kind.to_string(), None) - // } - - // ErrorKind::InvalidUtf8InPathParam { key } => { - // Error::PathParsing(kind.to_string(), Some(key.clone())) - // } - - // ErrorKind::UnsupportedType { .. } => { - // // this errors is caused by the programmer using an unsupported type - // // (such as nested maps) so respond with `500` instead - // status = StatusCode::INTERNAL_SERVER_ERROR; - // Error::internal_with_details(kind.to_string()) - // } - - // ErrorKind::Message(msg) => Error::PathParsing(msg.clone(), None), - // _ => Error::PathParsing( - // format!("Unhandled deserialization errors: {kind}"), - // None, - // ), - // }; - - (status, body) + (StatusCode::BAD_REQUEST, Error::path_parsing(inner)) } PathRejection::MissingPathParams(error) => ( StatusCode::INTERNAL_SERVER_ERROR, From f60467d5fd82ae5edfd264c14401cab8a29a6a32 Mon Sep 17 00:00:00 2001 From: Xu_Mj <40650924+Xu-Mj@users.noreply.github.com> Date: Sun, 28 Jul 2024 10:12:27 +0800 Subject: [PATCH 4/7] feat: nothing --- api/src/handlers/files/file.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/api/src/handlers/files/file.rs b/api/src/handlers/files/file.rs index 8d95893..4fe4573 100644 --- a/api/src/handlers/files/file.rs +++ b/api/src/handlers/files/file.rs @@ -17,6 +17,7 @@ pub async fn upload( if let Some(field) = multipart.next_field().await.map_err(Error::internal)? { filename = field.file_name().unwrap_or_default().to_string(); let extension = Path::new(&filename).extension().and_then(OsStr::to_str); + // filename = extension.map(|v| format!("{}.{}", nanoid!(), v)).unwrap_or(nanoid!()); filename = match extension { None => nanoid!(), Some(e) => format!("{}.{}", nanoid!(), e), From 4efe098dddaad225fb1db8ee0386977957f7e92b Mon Sep 17 00:00:00 2001 From: Xu_Mj <40650924+Xu-Mj@users.noreply.github.com> Date: Sun, 28 Jul 2024 10:20:26 +0800 Subject: [PATCH 5/7] fix: protoc not found --- .github/workflows/rust_checks.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/rust_checks.yml b/.github/workflows/rust_checks.yml index 0f0ca37..3cbe12e 100644 --- a/.github/workflows/rust_checks.yml +++ b/.github/workflows/rust_checks.yml @@ -22,6 +22,7 @@ jobs: key: ${{ runner.os }}-lint-${{ hashFiles('**/Cargo.lock') }} - name: Cache | Protoc + id: cache_protoc uses: actions/cache@v3 with: path: /opt/protoc @@ -35,6 +36,7 @@ jobs: cd /opt/protoc wget https://github.com/protocolbuffers/protobuf/releases/download/v23.4/protoc-23.4-linux-x86_64.zip unzip protoc-23.4-linux-x86_64.zip -d /opt/protoc + echo "/opt/protoc/bin" >> $GITHUB_PATH - name: Cache | Dependencies uses: actions/cache@v3 From a86e09ab6c680f2dcae7f847f2d34cf9ae524622 Mon Sep 17 00:00:00 2001 From: Xu_Mj <40650924+Xu-Mj@users.noreply.github.com> Date: Sun, 28 Jul 2024 10:32:44 +0800 Subject: [PATCH 6/7] fix: protoc not found in check step --- .github/workflows/rust_checks.yml | 51 ++++++++++++++++++------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/.github/workflows/rust_checks.yml b/.github/workflows/rust_checks.yml index 3cbe12e..36f933b 100644 --- a/.github/workflows/rust_checks.yml +++ b/.github/workflows/rust_checks.yml @@ -36,20 +36,9 @@ jobs: cd /opt/protoc wget https://github.com/protocolbuffers/protobuf/releases/download/v23.4/protoc-23.4-linux-x86_64.zip unzip protoc-23.4-linux-x86_64.zip -d /opt/protoc - echo "/opt/protoc/bin" >> $GITHUB_PATH - - name: Cache | Dependencies - uses: actions/cache@v3 - with: - path: /usr/local/include/librdkafka - key: librdkafka-dev-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }} - restore-keys: librdkafka-dev-${{ runner.os }}- - - - name: Install | Dependencies - if: steps.cache_dependencies.outputs.cache-hit != 'true' - run: | - sudo apt update - sudo apt install -y librdkafka-dev + - name: Add Protoc to PATH + run: echo "/opt/protoc/bin" >> $GITHUB_PATH - name: Setup | Install rustup run: | @@ -84,11 +73,6 @@ jobs: - name: Setup | Checkout uses: actions/checkout@v4 - - name: Setup | Install rustup - run: | - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - source $HOME/.cargo/env - - name: Setup | Cache Cargo uses: actions/cache@v4 with: @@ -99,6 +83,33 @@ jobs: target/ key: ${{ runner.os }}-check-${{ matrix.rust }}-${{ hashFiles('**/Cargo.lock') }} + - name: Cache | Protoc + id: cache_protoc_check + uses: actions/cache@v3 + with: + path: /opt/protoc + key: protoc-${{ runner.os }}-23.x + restore-keys: protoc-${{ runner.os }}- + + - name: Install | Protoc + if: steps.cache_protoc_check.outputs.cache-hit != 'true' + run: | + mkdir -p /opt/protoc + cd /opt/protoc + wget https://github.com/protocolbuffers/protobuf/releases/download/v23.4/protoc-23.4-linux-x86_64.zip + unzip protoc-23.4-linux-x86_64.zip -d /opt/protoc + + - name: Add Protoc to PATH + run: echo "/opt/protoc/bin" >> $GITHUB_PATH + + - name: Set PROTOC environment variable + run: echo "PROTOC=/opt/protoc/bin/protoc" >> $GITHUB_ENV + + - name: Setup | Install rustup + run: | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + source $HOME/.cargo/env + - name: Setup | Disable rustup self-update run: | rustup set auto-self-update disable @@ -118,7 +129,3 @@ jobs: - name: Setup | check-all-features run: | cargo binstall -y cargo-all-features - - - name: Build | Check all features - run: | - cargo check-all-features From 0a9edd364fa07fb0bac75ef017ec94e713252b00 Mon Sep 17 00:00:00 2001 From: Xu_Mj <40650924+Xu-Mj@users.noreply.github.com> Date: Sun, 28 Jul 2024 10:37:37 +0800 Subject: [PATCH 7/7] fix: check error about feature --- .github/workflows/rust_checks.yml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/rust_checks.yml b/.github/workflows/rust_checks.yml index 36f933b..b9666df 100644 --- a/.github/workflows/rust_checks.yml +++ b/.github/workflows/rust_checks.yml @@ -120,12 +120,4 @@ jobs: rustup default ${{ matrix.rust }} - name: Build | Check - run: cargo check --all - - - name: Setup | binstall - run: | - curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash - - - name: Setup | check-all-features - run: | - cargo binstall -y cargo-all-features + run: cargo check --no-default-features --features=static