refactor: clean up presentation layer — AppState grouping, multipart extractor, thin handlers

This commit is contained in:
2026-05-31 06:14:19 +02:00
parent 34b231a8f6
commit 2d9dd2c2d0
14 changed files with 199 additions and 258 deletions

View File

@@ -1,5 +1,7 @@
pub mod auth;
pub mod json;
pub mod multipart_upload;
pub use auth::JwtClaims;
pub use json::ValidatedJson;
pub use multipart_upload::UploadedAsset;

View File

@@ -0,0 +1,74 @@
use axum::extract::Multipart;
use bytes::Bytes;
use domain::errors::DomainError;
use domain::value_objects::SystemId;
use crate::constants::DEFAULT_DEVICE_ID;
use crate::errors::AppError;
pub struct UploadedAsset {
pub filename: String,
pub data: Bytes,
pub target_path_id: SystemId,
pub client_device_id: String,
}
impl UploadedAsset {
pub async fn from_multipart(mut multipart: Multipart) -> Result<Self, AppError> {
let mut file_data: Option<Bytes> = None;
let mut filename: Option<String> = None;
let mut target_path_id: Option<uuid::Uuid> = None;
let mut client_device_id = DEFAULT_DEVICE_ID.to_string();
while let Some(field) = multipart
.next_field()
.await
.map_err(|e| AppError::from(DomainError::Validation(e.to_string())))?
{
let name = field.name().unwrap_or("").to_string();
match name.as_str() {
"file" => {
filename = field.file_name().map(|s| s.to_string());
file_data = Some(
field
.bytes()
.await
.map_err(|e| AppError::from(DomainError::Internal(e.to_string())))?,
);
}
"target_path_id" => {
let text = field
.text()
.await
.map_err(|e| AppError::from(DomainError::Validation(e.to_string())))?;
target_path_id = Some(
text.parse::<uuid::Uuid>()
.map_err(|e| AppError::from(DomainError::Validation(e.to_string())))?,
);
}
"client_device_id" => {
client_device_id = field
.text()
.await
.map_err(|e| AppError::from(DomainError::Validation(e.to_string())))?;
}
_ => {}
}
}
let data = file_data
.ok_or_else(|| AppError::from(DomainError::Validation("Missing file field".into())))?;
let fname = filename
.ok_or_else(|| AppError::from(DomainError::Validation("Missing filename".into())))?;
let path_id = target_path_id.ok_or_else(|| {
AppError::from(DomainError::Validation("Missing target_path_id".into()))
})?;
Ok(Self {
filename: fname,
data,
target_path_id: SystemId::from_uuid(path_id),
client_device_id,
})
}
}