feat: Enhance validation and permissions handling across controllers

- Added `ValidatedJson` extractor for automatic JSON validation in `events_controller.rs`, `testimonials_controller.rs`, `mentors_controller.rs`, `gacha_items_controller.rs`, and `hackathon_controller.rs`.
- Replaced manual permission checks with `require_permissions!` and `require_auth!` macros in relevant controllers to streamline permission handling.
- Introduced `sanitization` utilities in `sanitization.rs` for improved input sanitization.
- Added `permission_macros.rs` to encapsulate permission checking logic and reduce boilerplate.
- Updated dependencies in `Cargo.toml` to include `serde_json` and `validator`.
- Implemented error handling improvements in `notification_service.rs` for better response management.
This commit is contained in:
MythEclipse
2025-10-28 14:04:41 +07:00
parent d4a6c4c9ea
commit b9a51ce6cc
17 changed files with 551 additions and 225 deletions
@@ -7,12 +7,12 @@ use super::{
};
use axum::extract::{Path, Query};
use axum::response::IntoResponse;
use axum::{Extension, Json, http::HeaderMap};
use axum::{Extension, http::HeaderMap};
use imphnen_libs::{
AppState, MessageResponseDto, MetaRequestDto, ResponseListSuccessDto,
ResponseSuccessDto,
ResponseSuccessDto, ValidatedJson,
};
use imphnen_iam::{PermissionsEnum, permissions_guard};
use imphnen_iam::{PermissionsEnum, require_permissions};
#[utoipa::path(
get,
@@ -71,12 +71,11 @@ pub async fn get_event_by_id(
pub async fn post_create_event(
headers: HeaderMap,
Extension(state): Extension<AppState>,
Json(payload): Json<EventsCreateRequestDto>,
ValidatedJson(payload): ValidatedJson<EventsCreateRequestDto>,
) -> impl IntoResponse {
match permissions_guard(headers, Extension(state), vec![PermissionsEnum::Administrator]).await {
Ok((_claims, state)) => EventsService::create_event(&state, payload).await,
Err(response) => response,
}
require_permissions!(headers, state, [PermissionsEnum::Administrator], {
EventsService::create_event(&state, payload).await
})
}
#[utoipa::path(
@@ -98,12 +97,11 @@ pub async fn patch_update_event(
headers: HeaderMap,
Extension(state): Extension<AppState>,
Path(id): Path<String>,
Json(payload): Json<EventsUpdateRequestDto>,
ValidatedJson(payload): ValidatedJson<EventsUpdateRequestDto>,
) -> impl IntoResponse {
match permissions_guard(headers, Extension(state), vec![PermissionsEnum::Administrator]).await {
Ok((_claims, state)) => EventsService::update_event(&state, id, payload).await,
Err(response) => response,
}
require_permissions!(headers, state, [PermissionsEnum::Administrator], {
EventsService::update_event(&state, id, payload).await
})
}
#[utoipa::path(
@@ -125,8 +123,7 @@ pub async fn delete_event(
Extension(state): Extension<AppState>,
Path(id): Path<String>,
) -> impl IntoResponse {
match permissions_guard(headers, Extension(state), vec![PermissionsEnum::Administrator]).await {
Ok((_claims, state)) => EventsService::delete_event(&state, id).await,
Err(response) => response,
}
require_permissions!(headers, state, [PermissionsEnum::Administrator], {
EventsService::delete_event(&state, id).await
})
}
@@ -7,13 +7,12 @@ use super::{
};
use axum::extract::{Path, Query};
use axum::response::IntoResponse;
use axum::{Extension, Json, http::HeaderMap};
use imphnen_iam::UsersDetailQueryDto;
use axum::{Extension, http::HeaderMap};
use imphnen_iam::{UsersDetailQueryDto, require_auth};
use imphnen_libs::{
AppState, MessageResponseDto, MetaRequestDto, ResponseListSuccessDto,
ResponseSuccessDto,
ResponseSuccessDto, ValidatedJson,
};
use imphnen_iam::permissions_guard;
#[utoipa::path(
get,
@@ -73,12 +72,11 @@ pub async fn post_create_testimonial(
headers: HeaderMap,
Extension(state): Extension<AppState>,
Extension(authenticated_user): Extension<UsersDetailQueryDto>,
Json(payload): Json<TestimonialsCreateRequestDto>,
ValidatedJson(payload): ValidatedJson<TestimonialsCreateRequestDto>,
) -> impl IntoResponse {
match permissions_guard(headers, Extension(state), vec![]).await {
Ok((_claims, state)) => TestimonialsService::create_testimonial(&state, payload, &authenticated_user).await,
Err(response) => response,
}
require_auth!(headers, state, {
TestimonialsService::create_testimonial(&state, payload, &authenticated_user).await
})
}
#[utoipa::path(
@@ -101,12 +99,11 @@ pub async fn patch_update_testimonial(
Path(id): Path<String>,
Extension(state): Extension<AppState>,
Extension(authenticated_user): Extension<UsersDetailQueryDto>,
Json(payload): Json<TestimonialsUpdateRequestDto>,
ValidatedJson(payload): ValidatedJson<TestimonialsUpdateRequestDto>,
) -> impl IntoResponse {
match permissions_guard(headers, Extension(state), vec![]).await {
Ok((_claims, state)) => TestimonialsService::update_testimonial(&state, id, payload, &authenticated_user).await,
Err(response) => response,
}
require_auth!(headers, state, {
TestimonialsService::update_testimonial(&state, id, payload, &authenticated_user).await
})
}
#[utoipa::path(
@@ -129,8 +126,7 @@ pub async fn delete_testimonial(
Extension(authenticated_user): Extension<UsersDetailQueryDto>,
Path(id): Path<String>,
) -> impl IntoResponse {
match permissions_guard(headers, Extension(state), vec![]).await {
Ok((_claims, state)) => TestimonialsService::delete_testimonial(&state, id, &authenticated_user).await,
Err(response) => response,
}
require_auth!(headers, state, {
TestimonialsService::delete_testimonial(&state, id, &authenticated_user).await
})
}