Skip to content

Commit

Permalink
chore: Update dependencies in Cargo.toml and fix linting warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
flaviodelgrosso committed Jul 15, 2024
1 parent dfec9ab commit 0fd5d03
Show file tree
Hide file tree
Showing 13 changed files with 79 additions and 61 deletions.
12 changes: 12 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"rust-analyzer.check.overrideCommand": [
"cargo",
"clippy",
"--tests",
"--message-format=json",
"--all",
"--",
"-W",
"clippy::pedantic"
]
}
24 changes: 12 additions & 12 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,23 @@ resolver = "2"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[workspace.dependencies]
anyhow = "1.0.79"
async-trait = "0.1.77"
axum = { version = "0.7.3", features = ["macros"] }
clap = { version = "4.4.13", features = ["env", "derive"] }
anyhow = "1.0.86"
async-trait = "0.1.81"
axum = { version = "0.7.5", features = ["macros"] }
clap = { version = "4.5.9", features = ["env", "derive"] }
dotenvy = "0.15.7"
lazy_static = "1.4.0"
mongodb = { version = "2.8.0" }
lazy_static = "1.5.0"
mongodb = { version = "3.0.1" }
pbkdf2 = "0.12.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.68"
time = "0.3.31"
thiserror = "1.0.56"
serde_json = "1.0.120"
time = "0.3.36"
thiserror = "1.0.62"
tokio = { version = "1", features = ["full"] }
tokio-stream = { version = "0.1.14" }
tokio-stream = { version = "0.1.15" }
tower = { version = "0.4.13", features = ["timeout", "buffer", "limit"] }
tower-http = { version = "0.5.0", features = ["fs", "trace", "cors"] }
tower-http = { version = "0.5.2", features = ["fs", "trace", "cors"] }
tracing = { version = "0.1.40" }
tracing-appender = "0.2.3"
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
validator = { version = "0.16.1", features = ["derive"] }
validator = { version = "0.18.1", features = ["derive"] }
14 changes: 14 additions & 0 deletions crates/database/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@ pub struct Database {
}

impl Database {
/// Creates a new `Database` instance.
///
/// # Arguments
///
/// * `config` - An `Arc` containing the application configuration.
///
/// # Returns
///
/// * `AppResult<Self>` - A result containing the `Database` instance or an error.
///
/// # Errors
///
/// This function will return an error if the `MongoDB` client cannot be initialized
/// or if the specified database or collection cannot be accessed.
pub async fn new(config: Arc<AppConfig>) -> AppResult<Self> {
let client = Client::with_uri_str(&config.mongo_uri).await?;
let db = client.database(&config.mongo_db);
Expand Down
14 changes: 8 additions & 6 deletions crates/database/src/user/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use tokio_stream::StreamExt;
use crate::{user::model::User, Database};
use utils::AppResult;

#[allow(clippy::module_name_repetitions)]
pub type DynUserRepository = Arc<dyn UserRepositoryTrait + Send + Sync>;

#[async_trait]
Expand Down Expand Up @@ -53,22 +54,22 @@ impl UserRepositoryTrait for Database {
password: password.to_string(),
};

let user = self.user_col.insert_one(new_doc, None).await?;
let user = self.user_col.insert_one(new_doc).await?;

Ok(user)
}

async fn get_user_by_email(&self, email: &str) -> AppResult<Option<User>> {
let filter = doc! {"email": email};
let user_detail = self.user_col.find_one(filter, None).await?;
let user_detail = self.user_col.find_one(filter).await?;

Ok(user_detail)
}

async fn get_user_by_id(&self, id: &str) -> AppResult<Option<User>> {
let obj_id = ObjectId::parse_str(id)?;
let filter = doc! {"_id": obj_id};
let user_detail = self.user_col.find_one(filter, None).await?;
let user_detail = self.user_col.find_one(filter).await?;

Ok(user_detail)
}
Expand All @@ -91,21 +92,22 @@ impl UserRepositoryTrait for Database {
},
};

let updated_doc = self.user_col.update_one(filter, new_doc, None).await?;
let updated_doc = self.user_col.update_one(filter, new_doc).await?;

Ok(updated_doc)
}

async fn delete_user(&self, id: &str) -> AppResult<DeleteResult> {
let obj_id = ObjectId::parse_str(id)?;
let filter = doc! {"_id": obj_id};
let user_detail = self.user_col.delete_one(filter, None).await?;
let user_detail = self.user_col.delete_one(filter).await?;

Ok(user_detail)
}

async fn get_all_users(&self) -> AppResult<Vec<User>> {
let mut cursor = self.user_col.find(None, None).await?;
let filter = doc! {};
let mut cursor = self.user_col.find(filter).await?;

let mut users: Vec<User> = Vec::new();
while let Some(doc) = cursor.next().await {
Expand Down
2 changes: 1 addition & 1 deletion crates/server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ path = "src/main.rs"
anyhow = { workspace = true }
async-trait = { workspace = true }
axum = { workspace = true }
axum-extra = { version = "0.9.1", features = ["cookie"] }
axum-extra = { version = "0.9.3", features = ["cookie"] }
clap = { workspace = true }
database = { path = "../database" }
dotenvy = { workspace = true }
Expand Down
8 changes: 4 additions & 4 deletions crates/server/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{logger::Logger, router::AppRouter};
pub struct ApplicationServer;
impl ApplicationServer {
pub async fn serve(config: Arc<AppConfig>) -> anyhow::Result<()> {
let _guard = Logger::new(config.cargo_env);
let _guard = Logger::init(config.cargo_env);

let address = format!("{}:{}", config.app_host, config.app_port);
let tcp_listener = tokio::net::TcpListener::bind(address)
Expand All @@ -27,7 +27,7 @@ impl ApplicationServer {

let db = Database::new(config.clone()).await?;
let services = Services::new(db);
let router = AppRouter::new(services);
let router = AppRouter::init(services);

serve(tcp_listener, router)
.with_graceful_shutdown(Self::shutdown_signal())
Expand Down Expand Up @@ -56,8 +56,8 @@ impl ApplicationServer {
let terminate = std::future::pending::<()>();

tokio::select! {
_ = ctrl_c => {},
_ = terminate => {},
() = ctrl_c => {},
() = terminate => {},
}

tracing::warn!("❌ Signal received, starting graceful shutdown...");
Expand Down
1 change: 1 addition & 0 deletions crates/server/src/dtos/user_dto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize};
use validator::Validate;

#[derive(Clone, Serialize, Deserialize, Debug, Validate, Default)]
#[allow(clippy::module_name_repetitions)]
pub struct SignUpUserDto {
#[validate(required, length(min = 1))]
pub name: Option<String>,
Expand Down
2 changes: 1 addition & 1 deletion crates/server/src/logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use utils::CargoEnv;

pub struct Logger;
impl Logger {
pub fn new(cargo_env: CargoEnv) -> WorkerGuard {
pub fn init(cargo_env: CargoEnv) -> WorkerGuard {
let (non_blocking, guard) = match cargo_env {
CargoEnv::Development => {
let console_logger = std::io::stdout();
Expand Down
11 changes: 6 additions & 5 deletions crates/server/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ lazy_static! {
static ref HTTP_TIMEOUT: u64 = 30;
}

#[allow(clippy::module_name_repetitions)]
pub struct AppRouter;
impl AppRouter {
pub fn new(services: Services) -> Router {
pub fn init(services: Services) -> Router {
let cors = CorsLayer::new()
.allow_origin(Any)
.allow_methods([
Expand All @@ -41,7 +42,7 @@ impl AppRouter {

let index = ServeDir::new("dist").not_found_service(ServeFile::new("dist/index.html"));

let router = Router::new()
Router::new()
.nest_service("/", index)
.nest("/api/v1", api::app())
.layer(cors)
Expand All @@ -54,11 +55,10 @@ impl AppRouter {
.layer(BufferLayer::new(1024))
.layer(RateLimitLayer::new(5, Duration::from_secs(1))),
)
.fallback(Self::handle_404);

router
.fallback(Self::handle_404)
}

#[allow(clippy::unused_async)]
async fn handle_404() -> impl IntoResponse {
(
StatusCode::NOT_FOUND,
Expand All @@ -69,6 +69,7 @@ impl AppRouter {
)
}

#[allow(clippy::unused_async)]
async fn handle_timeout_error(err: BoxError) -> (StatusCode, Json<serde_json::Value>) {
if err.is::<tower::timeout::error::Elapsed>() {
(
Expand Down
14 changes: 8 additions & 6 deletions crates/server/src/services/user_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ use utils::{AppError, AppResult};

use crate::dtos::user_dto::SignUpUserDto;

#[allow(clippy::module_name_repetitions)]
pub type DynUserService = Arc<dyn UserServiceTrait + Send + Sync>;

#[async_trait]
#[allow(clippy::module_name_repetitions)]
pub trait UserServiceTrait {
async fn get_current_user(&self, user_id: &str) -> AppResult<Option<User>>;
// async fn get_current_user(&self, user_id: &str) -> AppResult<Option<User>>;

async fn get_all_users(&self) -> AppResult<Vec<User>>;

Expand Down Expand Up @@ -41,7 +43,7 @@ impl UserServiceTrait for UserService {

if existing_user.is_some() {
error!("user {:?} already exists", email);
return Err(AppError::Conflict(format!("email {} is taken", email)));
return Err(AppError::Conflict(format!("email {email} is taken")));
}

let new_user = self
Expand All @@ -54,11 +56,11 @@ impl UserServiceTrait for UserService {
Ok(new_user)
}

async fn get_current_user(&self, user_id: &str) -> AppResult<Option<User>> {
let user = self.repository.get_user_by_id(user_id).await?;
// async fn get_current_user(&self, user_id: &str) -> AppResult<Option<User>> {
// let user = self.repository.get_user_by_id(user_id).await?;

Ok(user)
}
// Ok(user)
// }

async fn get_all_users(&self) -> AppResult<Vec<User>> {
let users = self.repository.get_all_users().await?;
Expand Down
2 changes: 1 addition & 1 deletion crates/utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ metadata.workspace = true
anyhow = { workspace = true }
axum = { workspace = true }
clap = { workspace = true }
jsonwebtoken = "9.2.0"
jsonwebtoken = "9.3.0"
mongodb = { workspace = true }
rust-argon2 = "2.1.0"
serde = { workspace = true }
Expand Down
1 change: 1 addition & 0 deletions crates/utils/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub enum CargoEnv {
}

#[derive(clap::Parser)]
#[allow(clippy::module_name_repetitions)]
pub struct AppConfig {
#[clap(long, env, value_enum)]
pub cargo_env: CargoEnv,
Expand Down
35 changes: 10 additions & 25 deletions crates/utils/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub struct HttpError {
}

impl HttpError {
#[must_use]
pub fn new(error: String) -> Self {
Self { error }
}
Expand Down Expand Up @@ -71,47 +72,31 @@ pub enum AppError {
}

impl AppError {
#[must_use]
/// Maps `validator`'s `ValidationrErrors` to a simple map of property name/error messages structure.
pub fn unprocessable_entity(errors: ValidationErrors) -> Response {
let mut validation_errors = ErrorMap::new();

for (field_property, error_kind) in errors.into_errors() {
if let ValidationErrorsKind::Field(field_meta) = error_kind.clone() {
for error in field_meta.into_iter() {
for error in field_meta {
validation_errors
.entry(Cow::from(field_property))
.or_insert_with(Vec::new)
.or_default()
.push(error.message.unwrap_or_else(|| {
let params: Vec<Cow<'static, str>> = error
.params
.iter()
.filter(|(key, _value)| key.to_owned() != "value")
.map(|(key, value)| {
Cow::from(format!("{} value is {}", key, value.to_string()))
})
.filter(|(key, _value)| *key != "value")
.map(|(key, value)| Cow::from(format!("{key} value is {value}")))
.collect();

if params.len() >= 1 {
Cow::from(params.join(", "))
if params.is_empty() {
Cow::from(format!("{field_property} is required"))
} else {
Cow::from(format!("{} is required", field_property))
Cow::from(params.join(", "))
}
}))
}
}

if let ValidationErrorsKind::Struct(meta) = error_kind.clone() {
for (struct_property, struct_error_kind) in meta.into_errors() {
if let ValidationErrorsKind::Field(field_meta) = struct_error_kind {
for error in field_meta.into_iter() {
validation_errors
.entry(Cow::from(struct_property))
.or_insert_with(Vec::new)
.push(error.message.unwrap_or_else(|| {
Cow::from(format!("{} is required", struct_property))
}));
}
}
}));
}
}
}
Expand Down

0 comments on commit 0fd5d03

Please sign in to comment.