refactor: remove serde from domain entities for Clean Architecture compliance
- Remove Serialize/Deserialize from File, Folder, Session, User, Contact entities - Create contact_persistence_dto.rs for JSONB persistence in infrastructure layer - Update contact_pg_repository to use persistence DTOs - Fix dependency on zip crate (downgrade from 7.2.0 to 2.1.0) - Fix unused variable warnings in main.rs - Move PathService import from domain to infrastructure - Add missing fields to CoreServices and RepositoryServices - Create proper service initialization in main.rs Clean Architecture improvements: - Domain layer no longer depends on serde framework - Persistence concerns isolated to infrastructure layer - TokenClaims in auth_service.rs is only exception (required for JWT)
This commit is contained in:
@@ -12,7 +12,7 @@ use crate::application::dtos::user_dto::{
|
||||
LoginDto, RegisterDto, UserDto, ChangePasswordDto, RefreshTokenDto, AuthResponseDto
|
||||
};
|
||||
use crate::interfaces::middleware::auth::CurrentUser;
|
||||
use crate::common::errors::AppError;
|
||||
use crate::interfaces::errors::AppError;
|
||||
|
||||
pub fn auth_routes() -> Router<Arc<AppState>> {
|
||||
Router::new()
|
||||
|
||||
@@ -39,7 +39,6 @@ pub struct BatchFolderOperationRequest {
|
||||
pub recursive: bool,
|
||||
/// ID de la carpeta destino (opcional)
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[allow(dead_code)]
|
||||
pub target_folder_id: Option<String>,
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ use axum::{
|
||||
response::IntoResponse,
|
||||
Json,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use serde_json::json;
|
||||
|
||||
use crate::common::di::AppState;
|
||||
|
||||
@@ -1,362 +0,0 @@
|
||||
use axum::{
|
||||
Router,
|
||||
routing::{get, put, delete, any},
|
||||
extract::{Path, State, Request},
|
||||
http::{StatusCode, HeaderMap},
|
||||
response::{IntoResponse, Response},
|
||||
body::Body,
|
||||
Json,
|
||||
};
|
||||
use tracing::error;
|
||||
use std::sync::Arc;
|
||||
use serde_json::json;
|
||||
|
||||
use crate::common::di::AppState;
|
||||
use crate::application::dtos::calendar_dto::{
|
||||
CalendarDto, CreateCalendarDto, UpdateCalendarDto,
|
||||
CalendarEventDto, CreateEventDto as CreateCalendarEventDto,
|
||||
UpdateEventDto as UpdateCalendarEventDto
|
||||
};
|
||||
|
||||
// CalDAV handler implementation
|
||||
pub fn caldav_routes() -> Router<AppState> {
|
||||
Router::new()
|
||||
// Calendar operations
|
||||
.route("/calendars", get(list_calendars))
|
||||
.route("/calendars/:calendar_id",
|
||||
get(get_calendar)
|
||||
.put(update_calendar)
|
||||
.delete(delete_calendar)
|
||||
)
|
||||
.route("/calendars/:calendar_id/events",
|
||||
get(list_events)
|
||||
.post(create_event)
|
||||
)
|
||||
.route("/calendars/:calendar_id/events/:event_id",
|
||||
get(get_event)
|
||||
.put(update_event)
|
||||
.delete(delete_event)
|
||||
)
|
||||
}
|
||||
|
||||
async fn list_calendars(
|
||||
State(state): State<AppState>,
|
||||
) -> impl IntoResponse {
|
||||
let user_id = "default_user"; // In production, get this from auth middleware
|
||||
|
||||
match &state.calendar_service {
|
||||
Some(calendar_service) => {
|
||||
let params = json!({
|
||||
"user_id": user_id
|
||||
});
|
||||
|
||||
match calendar_service.handle_request("list_user_calendars", params).await {
|
||||
Ok(result) => {
|
||||
let calendars: Vec<CalendarDto> = serde_json::from_value(result)
|
||||
.unwrap_or_else(|_| Vec::new());
|
||||
(StatusCode::OK, Json(calendars))
|
||||
},
|
||||
Err(e) => {
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(json!({
|
||||
"error": format!("Failed to list calendars: {}", e)
|
||||
})))
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
(StatusCode::NOT_IMPLEMENTED, Json(json!({
|
||||
"error": "Calendar service not available"
|
||||
})))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_calendar(
|
||||
State(state): State<AppState>,
|
||||
Path(calendar_id): Path<String>,
|
||||
) -> impl IntoResponse {
|
||||
let user_id = "default_user"; // In production, get this from auth middleware
|
||||
|
||||
match &state.calendar_service {
|
||||
Some(calendar_service) => {
|
||||
let params = json!({
|
||||
"calendar_id": calendar_id,
|
||||
"user_id": user_id
|
||||
});
|
||||
|
||||
match calendar_service.handle_request("get_calendar", params).await {
|
||||
Ok(result) => {
|
||||
let calendar: CalendarDto = serde_json::from_value(result)
|
||||
.unwrap_or_else(|_| CalendarDto::default());
|
||||
(StatusCode::OK, Json(calendar))
|
||||
},
|
||||
Err(e) => {
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(json!({
|
||||
"error": format!("Failed to get calendar: {}", e)
|
||||
})))
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
(StatusCode::NOT_IMPLEMENTED, Json(json!({
|
||||
"error": "Calendar service not available"
|
||||
})))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn update_calendar(
|
||||
State(state): State<AppState>,
|
||||
Path(calendar_id): Path<String>,
|
||||
Json(update): Json<UpdateCalendarDto>,
|
||||
) -> impl IntoResponse {
|
||||
let user_id = "default_user"; // In production, get this from auth middleware
|
||||
|
||||
// Set the user ID in the update
|
||||
let mut update_with_user = update;
|
||||
update_with_user.user_id = user_id.to_string();
|
||||
|
||||
match &state.calendar_service {
|
||||
Some(calendar_service) => {
|
||||
match calendar_service.handle_request("update_calendar", json!({
|
||||
"calendar_id": calendar_id,
|
||||
"name": update_with_user.name,
|
||||
"description": update_with_user.description,
|
||||
"color": update_with_user.color,
|
||||
"is_public": update_with_user.is_public,
|
||||
"user_id": update_with_user.user_id
|
||||
})).await {
|
||||
Ok(result) => {
|
||||
let calendar: CalendarDto = serde_json::from_value(result)
|
||||
.unwrap_or_else(|_| CalendarDto::default());
|
||||
(StatusCode::OK, Json(calendar))
|
||||
},
|
||||
Err(e) => {
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(json!({
|
||||
"error": format!("Failed to update calendar: {}", e)
|
||||
})))
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
(StatusCode::NOT_IMPLEMENTED, Json(json!({
|
||||
"error": "Calendar service not available"
|
||||
})))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn delete_calendar(
|
||||
State(state): State<AppState>,
|
||||
Path(calendar_id): Path<String>,
|
||||
) -> impl IntoResponse {
|
||||
let user_id = "default_user"; // In production, get this from auth middleware
|
||||
|
||||
match &state.calendar_service {
|
||||
Some(calendar_service) => {
|
||||
let params = json!({
|
||||
"calendar_id": calendar_id,
|
||||
"user_id": user_id
|
||||
});
|
||||
|
||||
match calendar_service.handle_request("delete_calendar", params).await {
|
||||
Ok(_) => {
|
||||
(StatusCode::NO_CONTENT, Json(json!({})))
|
||||
},
|
||||
Err(e) => {
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(json!({
|
||||
"error": format!("Failed to delete calendar: {}", e)
|
||||
})))
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
(StatusCode::NOT_IMPLEMENTED, Json(json!({
|
||||
"error": "Calendar service not available"
|
||||
})))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn list_events(
|
||||
State(state): State<AppState>,
|
||||
Path(calendar_id): Path<String>,
|
||||
) -> impl IntoResponse {
|
||||
let user_id = "default_user"; // In production, get this from auth middleware
|
||||
|
||||
match &state.calendar_service {
|
||||
Some(calendar_service) => {
|
||||
let params = json!({
|
||||
"calendar_id": calendar_id,
|
||||
"user_id": user_id
|
||||
});
|
||||
|
||||
match calendar_service.handle_request("list_events", params).await {
|
||||
Ok(result) => {
|
||||
let events: Vec<CalendarEventDto> = serde_json::from_value(result)
|
||||
.unwrap_or_else(|_| Vec::new());
|
||||
(StatusCode::OK, Json(events))
|
||||
},
|
||||
Err(e) => {
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(json!({
|
||||
"error": format!("Failed to list events: {}", e)
|
||||
})))
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
(StatusCode::NOT_IMPLEMENTED, Json(json!({
|
||||
"error": "Calendar service not available"
|
||||
})))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn create_event(
|
||||
State(state): State<AppState>,
|
||||
Path(calendar_id): Path<String>,
|
||||
Json(mut event): Json<CreateCalendarEventDto>,
|
||||
) -> impl IntoResponse {
|
||||
let user_id = "default_user"; // In production, get this from auth middleware
|
||||
|
||||
// Set the calendar ID and user ID in the event
|
||||
event.calendar_id = calendar_id;
|
||||
event.user_id = user_id.to_string();
|
||||
|
||||
match &state.calendar_service {
|
||||
Some(calendar_service) => {
|
||||
match calendar_service.handle_request("create_event", serde_json::to_value(event).unwrap()).await {
|
||||
Ok(result) => {
|
||||
let event: CalendarEventDto = serde_json::from_value(result)
|
||||
.unwrap_or_else(|_| CalendarEventDto::default());
|
||||
(StatusCode::CREATED, Json(event))
|
||||
},
|
||||
Err(e) => {
|
||||
let error_dto = CalendarEventDto::default();
|
||||
error!(
|
||||
"Failed to create event: {}",
|
||||
e
|
||||
);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(error_dto))
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
(StatusCode::NOT_IMPLEMENTED, Json(json!({
|
||||
"error": "Calendar service not available"
|
||||
})))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_event(
|
||||
State(state): State<AppState>,
|
||||
Path((calendar_id, event_id)): Path<(String, String)>,
|
||||
) -> impl IntoResponse {
|
||||
let user_id = "default_user"; // In production, get this from auth middleware
|
||||
|
||||
match &state.calendar_service {
|
||||
Some(calendar_service) => {
|
||||
let params = json!({
|
||||
"event_id": event_id,
|
||||
"user_id": user_id
|
||||
});
|
||||
|
||||
match calendar_service.handle_request("get_event", params).await {
|
||||
Ok(result) => {
|
||||
let event: CalendarEventDto = serde_json::from_value(result)
|
||||
.unwrap_or_else(|_| CalendarEventDto::default());
|
||||
(StatusCode::OK, Json(event))
|
||||
},
|
||||
Err(e) => {
|
||||
let error_dto = CalendarEventDto::default();
|
||||
error!(
|
||||
"Failed to get event: {}",
|
||||
e
|
||||
);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(error_dto))
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
(StatusCode::NOT_IMPLEMENTED, Json(json!({
|
||||
"error": "Calendar service not available"
|
||||
})))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn update_event(
|
||||
State(state): State<AppState>,
|
||||
Path((calendar_id, event_id)): Path<(String, String)>,
|
||||
Json(mut update): Json<UpdateCalendarEventDto>,
|
||||
) -> impl IntoResponse {
|
||||
let user_id = "default_user"; // In production, get this from auth middleware
|
||||
|
||||
// Set the user ID in the update
|
||||
update.user_id = user_id.to_string();
|
||||
|
||||
match &state.calendar_service {
|
||||
Some(calendar_service) => {
|
||||
let mut params = serde_json::to_value(update).unwrap();
|
||||
|
||||
// Add event_id to the params
|
||||
if let serde_json::Value::Object(ref mut map) = params {
|
||||
map.insert("event_id".to_string(), serde_json::Value::String(event_id));
|
||||
}
|
||||
|
||||
match calendar_service.handle_request("update_event", params).await {
|
||||
Ok(result) => {
|
||||
let event: CalendarEventDto = serde_json::from_value(result)
|
||||
.unwrap_or_else(|_| CalendarEventDto::default());
|
||||
(StatusCode::OK, Json(event))
|
||||
},
|
||||
Err(e) => {
|
||||
let error_dto = CalendarEventDto::default();
|
||||
error!(
|
||||
"Failed to update event: {}",
|
||||
e
|
||||
);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(error_dto))
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
(StatusCode::NOT_IMPLEMENTED, Json(json!({
|
||||
"error": "Calendar service not available"
|
||||
})))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn delete_event(
|
||||
State(state): State<AppState>,
|
||||
Path((calendar_id, event_id)): Path<(String, String)>,
|
||||
) -> impl IntoResponse {
|
||||
let user_id = "default_user"; // In production, get this from auth middleware
|
||||
|
||||
match &state.calendar_service {
|
||||
Some(calendar_service) => {
|
||||
let params = json!({
|
||||
"event_id": event_id,
|
||||
"user_id": user_id
|
||||
});
|
||||
|
||||
match calendar_service.handle_request("delete_event", params).await {
|
||||
Ok(_) => {
|
||||
(StatusCode::NO_CONTENT, Json(json!({})))
|
||||
},
|
||||
Err(e) => {
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(json!({
|
||||
"error": format!("Failed to delete event: {}", e)
|
||||
})))
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
(StatusCode::NOT_IMPLEMENTED, Json(json!({
|
||||
"error": "Calendar service not available"
|
||||
})))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
--- caldav_handler.rs
|
||||
+++ caldav_handler.rs
|
||||
@@ -242,9 +242,9 @@
|
||||
}
|
||||
},
|
||||
None => {
|
||||
- (StatusCode::NOT_IMPLEMENTED, Json(json\!({
|
||||
- "error": "Calendar service not available"
|
||||
- })))
|
||||
+ let error_dto = CalendarEventDto::default();
|
||||
+ error\!("Calendar service not available");
|
||||
+ (StatusCode::NOT_IMPLEMENTED, Json(error_dto))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -277,9 +277,9 @@
|
||||
}
|
||||
},
|
||||
None => {
|
||||
- (StatusCode::NOT_IMPLEMENTED, Json(json\!({
|
||||
- "error": "Calendar service not available"
|
||||
- })))
|
||||
+ let error_dto = CalendarEventDto::default();
|
||||
+ error\!("Calendar service not available");
|
||||
+ (StatusCode::NOT_IMPLEMENTED, Json(error_dto))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -320,9 +320,9 @@
|
||||
}
|
||||
},
|
||||
None => {
|
||||
- (StatusCode::NOT_IMPLEMENTED, Json(json\!({
|
||||
- "error": "Calendar service not available"
|
||||
- })))
|
||||
+ let error_dto = CalendarEventDto::default();
|
||||
+ error\!("Calendar service not available");
|
||||
+ (StatusCode::NOT_IMPLEMENTED, Json(error_dto))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,10 +7,6 @@ use axum::{
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use std::collections::HashMap;
|
||||
use futures::Stream;
|
||||
// use futures::StreamExt;
|
||||
use std::task::{Context, Poll};
|
||||
use std::pin::Pin;
|
||||
|
||||
use crate::application::services::file_service::{FileService, FileServiceError};
|
||||
use crate::infrastructure::services::compression_service::{
|
||||
@@ -46,35 +42,6 @@ type GlobalState = AppState;
|
||||
*/
|
||||
pub struct FileHandler;
|
||||
|
||||
// Simpler approach to make streams Unpin - use Pin<Box<dyn Stream>> directly
|
||||
struct BoxedStream<T> {
|
||||
inner: Pin<Box<dyn Stream<Item = T> + Send + 'static>>,
|
||||
}
|
||||
|
||||
impl<T> Stream for BoxedStream<T> {
|
||||
type Item = T;
|
||||
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
// Accessing the field directly is safe because BoxedStream is not a structural pinning type
|
||||
unsafe { self.get_unchecked_mut().inner.as_mut().poll_next(cx) }
|
||||
}
|
||||
}
|
||||
|
||||
// This is safe because BoxedStream's inner field is already Pin<Box<dyn Stream>>
|
||||
impl<T> Unpin for BoxedStream<T> {}
|
||||
|
||||
impl<T> BoxedStream<T> {
|
||||
#[allow(dead_code)]
|
||||
fn new<S>(stream: S) -> Self
|
||||
where
|
||||
S: Stream<Item = T> + Send + 'static,
|
||||
{
|
||||
BoxedStream {
|
||||
inner: Box::pin(stream),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FileHandler {
|
||||
/// Uploads a file
|
||||
pub async fn upload_file(
|
||||
|
||||
@@ -22,7 +22,7 @@ use crate::common::di::AppState;
|
||||
use crate::application::adapters::webdav_adapter::{WebDavAdapter, PropFindRequest, LockInfo, LockScope, LockType};
|
||||
use crate::interfaces::middleware::auth::CurrentUser;
|
||||
use crate::application::dtos::folder_dto::FolderDto;
|
||||
use crate::common::errors::AppError;
|
||||
use crate::interfaces::errors::AppError;
|
||||
|
||||
// Create a custom DAV header since it's not in the standard headers
|
||||
const HEADER_DAV: HeaderName = HeaderName::from_static("dav");
|
||||
|
||||
Reference in New Issue
Block a user