use axum::{Json, extract::State, http::StatusCode}; use serde::Deserialize; use thiserror::Error; use uuid::Uuid; use crate::{ domain::warren::{ models::{ auth_session::AuthRequest, file::{AbsoluteFilePath, AbsoluteFilePathError, FilePath, FilePathError}, share::{CreateShareBaseRequest, SharePassword, SharePasswordError}, }, ports::{AuthService, WarrenService}, }, inbound::http::{ AppState, handlers::{ShareData, extractors::SessionIdHeader}, responses::{ApiError, ApiSuccess}, }, }; #[derive(Debug, Clone, Deserialize)] #[serde(rename_all = "camelCase")] pub(super) struct CreateShareHttpRequestBody { warren_id: Uuid, path: String, lifetime: Option, password: Option, } #[derive(Debug, Error)] enum ParseCreateShareHttpRequestError { #[error(transparent)] FilePath(#[from] FilePathError), #[error(transparent)] AbsoluteFilePath(#[from] AbsoluteFilePathError), #[error(transparent)] SharePassword(#[from] SharePasswordError), } impl From for ApiError { fn from(e: ParseCreateShareHttpRequestError) -> Self { ApiError::BadRequest(e.to_string()) } } impl CreateShareHttpRequestBody { fn try_into_domain(self) -> Result { let path: AbsoluteFilePath = { let file_path = FilePath::new(&self.path)?; file_path.try_into()? }; let password = if let Some(password) = self.password { Some(SharePassword::new(&password)?) } else { None }; Ok(CreateShareBaseRequest::new( self.warren_id, path, password, self.lifetime, )) } } pub async fn create_share( State(state): State>, SessionIdHeader(session): SessionIdHeader, Json(request): Json, ) -> Result, ApiError> { let domain_request = AuthRequest::new(session, request.try_into_domain()?); state .auth_service .auth_warren_create_share(domain_request, state.warren_service.as_ref()) .await .map(|response| { ApiSuccess::new( StatusCode::CREATED, ShareData::from(response.share().clone()), ) }) .map_err(ApiError::from) }