030e59e
zhenyi
refactor(lib): migrate storage and security tier to central lib/config (auth, cache, db, email, jwt, payment, queue, rate_limit, storage)
030e59e
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<Uuid>,
pub filename: String,
pub content_type: String,
pub size_hint: Option<i64>,
}
#[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<i64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FinalizeUploadRequest {
pub size: i64,
pub content_type: String,
}
pub(crate) async fn presign_upload(
State(state): State<GatewayState>,
BearToken(token): BearToken,
AppRequest(req): AppRequest<PresignUploadRequest>,
) -> GatewayResult<AppResponseData<PresignedUploadResponse>> {
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<GatewayState>,
BearToken(token): BearToken,
Path(attachment_id): Path<Uuid>,
AppRequest(req): AppRequest<FinalizeUploadRequest>,
) -> GatewayResult<AppResponseData<AttachmentMeta>> {
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<GatewayState>,
BearToken(token): BearToken,
Path(attachment_id): Path<Uuid>,
) -> GatewayResult<AppResponseData<NoData>> {
state
.chat
.media()
.abort_upload(state.chat.auth(), &token, attachment_id)
.await?;
Ok(AppResponseData::empty())
}