use std::time::Duration; use axum::extract::{Path, State}; use chatlayer::AttachmentMeta; use export::data::{AppRequest, AppResponseData, NoData}; use serde::{Deserialize, Serialize}; use storagelayer::models::attachment::AttachmentOwner; use uuid::Uuid; use crate::auth::BearToken; use crate::error::GatewayResult; use crate::state::GatewayState; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PresignUploadRequest { pub owner: AttachmentOwner, pub owner_hint: Option, pub filename: String, pub content_type: String, pub size_hint: Option, } #[derive(Debug, Clone, Serialize)] pub struct PresignedUploadResponse { pub attachment_id: Uuid, pub upload_url: String, pub key: String, pub filename: String, pub content_type: String, pub size_hint: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct FinalizeUploadRequest { pub size: i64, pub content_type: String, } pub(crate) async fn presign_upload( State(state): State, BearToken(token): BearToken, AppRequest(req): AppRequest, ) -> GatewayResult> { let ttl = Duration::from_secs(state.settings.upload_presign_ttl_seconds); let upload = state .chat .media() .presign_upload( state.chat.auth(), &token, req.owner, req.owner_hint, &req.filename, &req.content_type, req.size_hint, ttl, ) .await?; Ok(AppResponseData::ok(PresignedUploadResponse { attachment_id: upload.attachment_id, upload_url: upload.upload_url.to_string(), key: upload.key, filename: upload.filename, content_type: upload.content_type, size_hint: upload.size_hint, })) } pub(crate) async fn finalize_upload( State(state): State, BearToken(token): BearToken, Path(attachment_id): Path, AppRequest(req): AppRequest, ) -> GatewayResult> { let meta = state .chat .media() .finalize_upload( state.chat.auth(), &token, attachment_id, req.size, &req.content_type, ) .await?; Ok(AppResponseData::ok(meta)) } pub(crate) async fn abort_upload( State(state): State, BearToken(token): BearToken, Path(attachment_id): Path, ) -> GatewayResult> { state .chat .media() .abort_upload(state.chat.auth(), &token, attachment_id) .await?; Ok(AppResponseData::empty()) }