diff --git a/src/handlers/attachments.rs b/src/handlers/attachments.rs index af20102..395306d 100644 --- a/src/handlers/attachments.rs +++ b/src/handlers/attachments.rs @@ -1,15 +1,17 @@ use std::{collections::HashMap, sync::Arc}; -use axum::{body::Bytes, extract::{Multipart, Path, State}, Extension, Json}; +use axum::{ + body::Bytes, + extract::{Multipart, Path, State}, + Extension, Json, +}; use chrono::Utc; use jsonwebtoken::{encode, EncodingKey, Header}; use log; use serde::{Deserialize, Serialize}; use serde_json::Value; use uuid::Uuid; -use worker::{ - query, wasm_bindgen::JsValue, Bucket, D1Database, Env, HttpMetadata, -}; +use worker::{query, wasm_bindgen::JsValue, Bucket, D1Database, Env, HttpMetadata}; use crate::{ auth::Claims, @@ -161,7 +163,7 @@ pub async fn create_attachment_v2( // Return upload URL pointing to local upload endpoint let url = upload_url(&env, &base_url, &cipher_id, &attachment_id, &claims.sub)?; let mut cipher_response: Cipher = cipher.into(); - hydrate_cipher_attachments(&db, &env, &base_url, &mut cipher_response, &claims.sub).await?; + hydrate_cipher_attachments(&db, &env, &mut cipher_response).await?; touch_cipher_updated_at(&db, &cipher_id).await?; db::touch_user_updated_at(&db, &claims.sub).await?; @@ -256,7 +258,6 @@ pub async fn upload_attachment_v2_data( pub async fn upload_attachment_legacy( claims: Claims, State(env): State>, - Extension(BaseUrl(base_url)): Extension, Path(cipher_id): Path, mut multipart: Multipart, ) -> Result, AppError> { @@ -313,7 +314,7 @@ pub async fn upload_attachment_legacy( // 返回最新的 Cipher(含附件) let mut cipher_response: Cipher = cipher.into(); - hydrate_cipher_attachments(&db, &env, &base_url, &mut cipher_response, &claims.sub).await?; + hydrate_cipher_attachments(&db, &env, &mut cipher_response).await?; Ok(Json(cipher_response)) } @@ -339,7 +340,7 @@ pub async fn get_attachment( } let url = download_url(&env, &base_url, &cipher_id, &attachment_id, &claims.sub)?; - Ok(Json(attachment.to_response(url))) + Ok(Json(attachment.to_response(Some(url)))) } /// DELETE /api/ciphers/{cipher_id}/attachment/{attachment_id} @@ -347,7 +348,6 @@ pub async fn get_attachment( pub async fn delete_attachment( claims: Claims, State(env): State>, - Extension(BaseUrl(base_url)): Extension, Path((cipher_id, attachment_id)): Path<(String, String)>, ) -> Result, AppError> { let bucket = require_bucket(&env)?; @@ -377,7 +377,7 @@ pub async fn delete_attachment( let mut cipher_response: Cipher = ensure_cipher_for_user(&db, &cipher_id, &claims.sub) .await? .into(); - hydrate_cipher_attachments(&db, &env, &base_url, &mut cipher_response, &claims.sub).await?; + hydrate_cipher_attachments(&db, &env, &mut cipher_response).await?; Ok(Json(AttachmentDeleteResponse { cipher: cipher_response, @@ -390,33 +390,23 @@ pub async fn delete_attachment( pub async fn delete_attachment_post( claims: Claims, State(env): State>, - Extension(BaseUrl(base_url)): Extension, Path((cipher_id, attachment_id)): Path<(String, String)>, ) -> Result, AppError> { - delete_attachment( - claims, - State(env), - Extension(BaseUrl(base_url)), - Path((cipher_id, attachment_id)), - ) - .await + delete_attachment(claims, State(env), Path((cipher_id, attachment_id))).await } - /// Attach attachment information to Cipher (used by other handlers) pub async fn hydrate_cipher_attachments( db: &D1Database, env: &Env, - base_url: &str, cipher: &mut Cipher, - user_id: &str, ) -> Result<(), AppError> { if !attachments_enabled(env) { cipher.attachments = None; return Ok(()); } - let mut map = load_attachment_map(db, env, base_url, &[cipher.id.clone()], user_id).await?; + let mut map = load_attachment_map(db, &[cipher.id.clone()]).await?; if let Some(list) = map.remove(&cipher.id) { if !list.is_empty() { cipher.attachments = Some(list); @@ -429,9 +419,7 @@ pub async fn hydrate_cipher_attachments( pub async fn hydrate_ciphers_attachments( db: &D1Database, env: &Env, - base_url: &str, ciphers: &mut [Cipher], - user_id: &str, ) -> Result<(), AppError> { if !attachments_enabled(env) { for cipher in ciphers.iter_mut() { @@ -441,7 +429,7 @@ pub async fn hydrate_ciphers_attachments( } let ids: Vec = ciphers.iter().map(|c| c.id.clone()).collect(); - let mut map = load_attachment_map(db, env, base_url, &ids, user_id).await?; + let mut map = load_attachment_map(db, &ids).await?; for cipher in ciphers.iter_mut() { if let Some(list) = map.remove(&cipher.id) { @@ -612,10 +600,7 @@ async fn fetch_attachment(db: &D1Database, attachment_id: &str) -> Result Result>, AppError> { if cipher_ids.is_empty() { return Ok(HashMap::new()); @@ -635,16 +620,10 @@ async fn load_attachment_map( let mut map: HashMap> = HashMap::new(); for attachment in attachments { - let url = download_url( - env, - base_url, - &attachment.cipher_id, - &attachment.id, - user_id, - )?; map.entry(attachment.cipher_id.clone()) .or_default() - .push(attachment.to_response(url)); + // URLs are minted on-demand via the download endpoint; skip pre-signing here. + .push(attachment.to_response(None)); } Ok(map) diff --git a/src/handlers/ciphers.rs b/src/handlers/ciphers.rs index f7d0485..2124f93 100644 --- a/src/handlers/ciphers.rs +++ b/src/handlers/ciphers.rs @@ -38,7 +38,6 @@ async fn fetch_cipher_for_user( pub async fn create_cipher( claims: Claims, State(env): State>, - Extension(BaseUrl(base_url)): Extension, Json(payload): Json, ) -> Result, AppError> { let db = db::get_db(&env)?; @@ -97,7 +96,7 @@ pub async fn create_cipher( .run() .await?; - attachments::hydrate_cipher_attachments(&db, env.as_ref(), &base_url, &mut cipher, &claims.sub) + attachments::hydrate_cipher_attachments(&db, env.as_ref(), &mut cipher) .await?; db::touch_user_updated_at(&db, &claims.sub).await?; @@ -108,7 +107,7 @@ pub async fn create_cipher( pub async fn update_cipher( claims: Claims, State(env): State>, - Extension(BaseUrl(base_url)): Extension, + Extension(BaseUrl(_base_url)): Extension, Path(id): Path, Json(payload): Json, ) -> Result, AppError> { @@ -210,7 +209,7 @@ pub async fn update_cipher( .run() .await?; - attachments::hydrate_cipher_attachments(&db, env.as_ref(), &base_url, &mut cipher, &claims.sub) + attachments::hydrate_cipher_attachments(&db, env.as_ref(), &mut cipher) .await?; db::touch_user_updated_at(&db, &claims.sub).await?; @@ -222,7 +221,6 @@ pub async fn update_cipher( pub async fn list_ciphers( claims: Claims, State(env): State>, - Extension(BaseUrl(base_url)): Extension, ) -> Result, AppError> { let db = db::get_db(&env)?; @@ -239,14 +237,7 @@ pub async fn list_ciphers( let mut ciphers: Vec = ciphers_db.into_iter().map(|c| c.into()).collect(); - attachments::hydrate_ciphers_attachments( - &db, - env.as_ref(), - &base_url, - &mut ciphers, - &claims.sub, - ) - .await?; + attachments::hydrate_ciphers_attachments(&db, env.as_ref(), &mut ciphers).await?; Ok(Json(CipherListResponse { data: ciphers, @@ -260,14 +251,13 @@ pub async fn list_ciphers( pub async fn get_cipher( claims: Claims, State(env): State>, - Extension(BaseUrl(base_url)): Extension, Path(id): Path, ) -> Result, AppError> { let db = db::get_db(&env)?; let cipher = fetch_cipher_for_user(&db, &id, &claims.sub).await?; let mut cipher: Cipher = cipher.into(); - attachments::hydrate_cipher_attachments(&db, env.as_ref(), &base_url, &mut cipher, &claims.sub) + attachments::hydrate_cipher_attachments(&db, env.as_ref(), &mut cipher) .await?; Ok(Json(cipher)) @@ -278,10 +268,9 @@ pub async fn get_cipher( pub async fn get_cipher_details( claims: Claims, state: State>, - extension: Extension, id: Path, ) -> Result, AppError> { - get_cipher(claims, state, extension, id).await + get_cipher(claims, state, id).await } /// PUT/POST /api/ciphers/{id}/partial @@ -289,7 +278,6 @@ pub async fn get_cipher_details( pub async fn update_cipher_partial( claims: Claims, State(env): State>, - Extension(BaseUrl(base_url)): Extension, Path(id): Path, Json(payload): Json, ) -> Result, AppError> { @@ -334,7 +322,7 @@ pub async fn update_cipher_partial( let cipher = fetch_cipher_for_user(&db, &id, user_id).await?; let mut cipher: Cipher = cipher.into(); - attachments::hydrate_cipher_attachments(&db, env.as_ref(), &base_url, &mut cipher, &claims.sub) + attachments::hydrate_cipher_attachments(&db, env.as_ref(), &mut cipher) .await?; Ok(Json(cipher)) @@ -482,7 +470,6 @@ pub async fn hard_delete_ciphers_bulk( pub async fn restore_cipher( claims: Claims, State(env): State>, - Extension(BaseUrl(base_url)): Extension, Path(id): Path, ) -> Result, AppError> { let db = db::get_db(&env)?; @@ -513,7 +500,7 @@ pub async fn restore_cipher( .ok_or(AppError::NotFound("Cipher not found".to_string()))?; let mut cipher: Cipher = cipher_db.into(); - attachments::hydrate_cipher_attachments(&db, env.as_ref(), &base_url, &mut cipher, &claims.sub) + attachments::hydrate_cipher_attachments(&db, env.as_ref(), &mut cipher) .await?; db::touch_user_updated_at(&db, &claims.sub).await?; @@ -535,7 +522,6 @@ pub struct BulkRestoreResponse { pub async fn restore_ciphers_bulk( claims: Claims, State(env): State>, - Extension(BaseUrl(base_url)): Extension, Json(payload): Json, ) -> Result, AppError> { let db = db::get_db(&env)?; @@ -582,14 +568,7 @@ pub async fn restore_ciphers_bulk( .map(|cipher| cipher.into()) .collect(); - attachments::hydrate_ciphers_attachments( - &db, - env.as_ref(), - &base_url, - &mut restored_ciphers, - &claims.sub, - ) - .await?; + attachments::hydrate_ciphers_attachments(&db, env.as_ref(), &mut restored_ciphers).await?; db::touch_user_updated_at(&db, &claims.sub).await?; @@ -607,7 +586,6 @@ pub async fn restore_ciphers_bulk( pub async fn create_cipher_simple( claims: Claims, State(env): State>, - Extension(BaseUrl(base_url)): Extension, Json(payload): Json, ) -> Result, AppError> { let db = db::get_db(&env)?; @@ -660,7 +638,7 @@ pub async fn create_cipher_simple( .run() .await?; - attachments::hydrate_cipher_attachments(&db, env.as_ref(), &base_url, &mut cipher, &claims.sub) + attachments::hydrate_cipher_attachments(&db, env.as_ref(), &mut cipher) .await?; db::touch_user_updated_at(&db, &claims.sub).await?; diff --git a/src/handlers/sync.rs b/src/handlers/sync.rs index 4f8369d..4ac9d9f 100644 --- a/src/handlers/sync.rs +++ b/src/handlers/sync.rs @@ -1,4 +1,4 @@ -use axum::{extract::State, Extension, Json}; +use axum::{extract::State, Json}; use serde_json::Value; use std::sync::Arc; use worker::Env; @@ -14,14 +14,12 @@ use crate::{ sync::{Profile, SyncResponse}, user::User, }, - BaseUrl, }; #[worker::send] pub async fn get_sync_data( claims: Claims, State(env): State>, - Extension(BaseUrl(base_url)): Extension, ) -> Result, AppError> { let user_id = claims.sub; let db = db::get_db(&env)?; @@ -67,7 +65,7 @@ pub async fn get_sync_data( .collect::>(); let mut ciphers = ciphers; - attachments::hydrate_ciphers_attachments(&db, env.as_ref(), &base_url, &mut ciphers, &user_id) + attachments::hydrate_ciphers_attachments(&db, env.as_ref(), &mut ciphers) .await?; let profile = Profile::from_user(user)?; diff --git a/src/models/attachment.rs b/src/models/attachment.rs index 382cff8..357bc4f 100644 --- a/src/models/attachment.rs +++ b/src/models/attachment.rs @@ -18,7 +18,8 @@ pub struct AttachmentDB { #[serde(rename_all = "camelCase")] pub struct AttachmentResponse { pub id: String, - pub url: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub url: Option, pub file_name: String, pub size: String, pub size_name: String, @@ -32,7 +33,7 @@ impl AttachmentDB { format!("{}/{}", self.cipher_id, self.id) } - pub fn to_response(&self, url: String) -> AttachmentResponse { + pub fn to_response(&self, url: Option) -> AttachmentResponse { AttachmentResponse { id: self.id.clone(), url,