remove download endpoint
This commit is contained in:
@@ -18,7 +18,6 @@ use uuid::Uuid;
|
|||||||
doc::get_document,
|
doc::get_document,
|
||||||
doc::update_document,
|
doc::update_document,
|
||||||
doc::delete_document,
|
doc::delete_document,
|
||||||
doc::download_document,
|
|
||||||
doc::download_with_token,
|
doc::download_with_token,
|
||||||
doc::move_document,
|
doc::move_document,
|
||||||
doc::assign_tags,
|
doc::assign_tags,
|
||||||
@@ -64,7 +63,6 @@ use uuid::Uuid;
|
|||||||
schemas::DocumentAssetObject,
|
schemas::DocumentAssetObject,
|
||||||
schemas::DocumentCorrespondent,
|
schemas::DocumentCorrespondent,
|
||||||
schemas::DocumentTag,
|
schemas::DocumentTag,
|
||||||
schemas::DocumentDownloadResponse,
|
|
||||||
schemas::UpdateDocumentRequest,
|
schemas::UpdateDocumentRequest,
|
||||||
schemas::BulkMoveDocumentsRequest,
|
schemas::BulkMoveDocumentsRequest,
|
||||||
schemas::BulkMoveDocumentsResponse,
|
schemas::BulkMoveDocumentsResponse,
|
||||||
@@ -270,15 +268,6 @@ mod doc {
|
|||||||
)]
|
)]
|
||||||
pub(super) fn restore_document() {}
|
pub(super) fn restore_document() {}
|
||||||
|
|
||||||
#[utoipa::path(
|
|
||||||
get,
|
|
||||||
path = "/api/documents/{id}/download",
|
|
||||||
params(("id" = Uuid, Path, description = "Document ID")),
|
|
||||||
responses((status = 200, description = "Download metadata", body = DocumentDownloadResponse)),
|
|
||||||
tag = "Documents"
|
|
||||||
)]
|
|
||||||
pub(super) fn download_document() {}
|
|
||||||
|
|
||||||
#[utoipa::path(
|
#[utoipa::path(
|
||||||
get,
|
get,
|
||||||
path = "/download/{token}",
|
path = "/download/{token}",
|
||||||
@@ -728,16 +717,6 @@ pub mod schemas {
|
|||||||
pub document: DocumentResponse,
|
pub document: DocumentResponse,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, ToSchema)]
|
|
||||||
pub struct DocumentDownloadResponse {
|
|
||||||
pub url: String,
|
|
||||||
pub expires_in: u64,
|
|
||||||
pub filename: String,
|
|
||||||
#[schema(nullable)]
|
|
||||||
pub content_type: Option<String>,
|
|
||||||
pub size_bytes: i64,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, ToSchema)]
|
#[derive(Serialize, Deserialize, ToSchema)]
|
||||||
pub struct DocumentMetadataUpdate {
|
pub struct DocumentMetadataUpdate {
|
||||||
pub value: Value,
|
pub value: Value,
|
||||||
|
|||||||
@@ -215,15 +215,6 @@ pub struct DocumentDetailResponse {
|
|||||||
pub document: DocumentResponse,
|
pub document: DocumentResponse,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, ToSchema)]
|
|
||||||
pub struct DocumentDownloadResponse {
|
|
||||||
pub url: String,
|
|
||||||
pub expires_in: u64,
|
|
||||||
pub filename: String,
|
|
||||||
pub content_type: Option<String>,
|
|
||||||
pub size_bytes: i64,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, ToSchema)]
|
#[derive(Serialize, ToSchema)]
|
||||||
pub struct BulkReanalyzeResponse {
|
pub struct BulkReanalyzeResponse {
|
||||||
pub queued: usize,
|
pub queued: usize,
|
||||||
@@ -1211,46 +1202,6 @@ pub async fn get_document_version(
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn download_document(
|
|
||||||
State(state): State<AppState>,
|
|
||||||
Path(document_id): Path<Uuid>,
|
|
||||||
TenantScopedConn {
|
|
||||||
mut conn,
|
|
||||||
tenant_id,
|
|
||||||
..
|
|
||||||
}: TenantScopedConn,
|
|
||||||
) -> AppResult<Json<DocumentDownloadResponse>> {
|
|
||||||
let doc: Document = documents::table
|
|
||||||
.find(document_id)
|
|
||||||
.filter(documents::tenant_id.eq(tenant_id))
|
|
||||||
.first(&mut conn)?;
|
|
||||||
if doc.deleted_at.is_some() {
|
|
||||||
return Err(AppError::not_found());
|
|
||||||
}
|
|
||||||
|
|
||||||
let version: DocumentVersion = document_versions::table
|
|
||||||
.find(doc.current_version_id)
|
|
||||||
.first(&mut conn)?;
|
|
||||||
|
|
||||||
let storage = state.storage_for_tenant(tenant_id)?;
|
|
||||||
|
|
||||||
let presigned_url = storage
|
|
||||||
.presign_get_object(
|
|
||||||
&version.s3_key,
|
|
||||||
Duration::from_secs(PRESIGNED_URL_EXPIRY_SECONDS),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.map_err(|err| AppError::internal(format!("failed to generate download URL: {err}")))?;
|
|
||||||
|
|
||||||
Ok(Json(DocumentDownloadResponse {
|
|
||||||
url: presigned_url,
|
|
||||||
expires_in: PRESIGNED_URL_EXPIRY_SECONDS,
|
|
||||||
filename: doc.original_name.clone(),
|
|
||||||
content_type: doc.content_type.clone(),
|
|
||||||
size_bytes: version.size_bytes,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn download_with_token(
|
pub async fn download_with_token(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
Path(token): Path<String>,
|
Path(token): Path<String>,
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ pub fn create_router(state: AppState) -> Router<()> {
|
|||||||
.delete(documents::delete_document)
|
.delete(documents::delete_document)
|
||||||
.patch(documents::update_document),
|
.patch(documents::update_document),
|
||||||
)
|
)
|
||||||
.route("/:id/download", get(documents::download_document))
|
|
||||||
.route(
|
.route(
|
||||||
"/:id/assets",
|
"/:id/assets",
|
||||||
get(documents::list_document_assets).post(documents::request_document_assets),
|
get(documents::list_document_assets).post(documents::request_document_assets),
|
||||||
|
|||||||
@@ -60,11 +60,6 @@ struct DocumentListItem {
|
|||||||
current_version: Option<DocumentVersionPayload>,
|
current_version: Option<DocumentVersionPayload>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct DocumentDownload {
|
|
||||||
filename: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct BulkReanalyze {
|
struct BulkReanalyze {
|
||||||
queued: usize,
|
queued: usize,
|
||||||
@@ -238,24 +233,6 @@ async fn upload_and_list_document() -> Result<()> {
|
|||||||
.download_path
|
.download_path
|
||||||
.starts_with("/download/"));
|
.starts_with("/download/"));
|
||||||
|
|
||||||
let download = app
|
|
||||||
.get(
|
|
||||||
&format!("/api/documents/{}/download", detail.document.id),
|
|
||||||
Some(&token),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
{
|
|
||||||
let status = download.status();
|
|
||||||
assert!(
|
|
||||||
status == StatusCode::OK
|
|
||||||
|| status == StatusCode::CREATED
|
|
||||||
|| status == StatusCode::NO_CONTENT
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let body = body_to_vec(download.into_body()).await?;
|
|
||||||
let download_info: DocumentDownload = serde_json::from_slice(&body)?;
|
|
||||||
assert_eq!(download_info.filename, "doc.txt");
|
|
||||||
|
|
||||||
let redirect = app.get(¤t_version.download_path, None).await?;
|
let redirect = app.get(¤t_version.download_path, None).await?;
|
||||||
assert_eq!(redirect.status(), StatusCode::TEMPORARY_REDIRECT);
|
assert_eq!(redirect.status(), StatusCode::TEMPORARY_REDIRECT);
|
||||||
let location = redirect
|
let location = redirect
|
||||||
|
|||||||
+12
-7
@@ -3107,13 +3107,18 @@ const AppLayout = () => {
|
|||||||
|
|
||||||
const request = (async () => {
|
const request = (async () => {
|
||||||
try {
|
try {
|
||||||
const { data } = await api.get(`/documents/${documentId}/download`);
|
const docResponse = await api.get(`/documents/${documentId}`);
|
||||||
const ttl = data.expires_in ? Math.max(data.expires_in - 60, 30) * 1000 : 5 * 60 * 1000;
|
const downloadPath = docResponse.data?.document?.current_version?.download_path;
|
||||||
|
if (!downloadPath || !resolveApiPath) {
|
||||||
|
throw new Error('Document missing download path');
|
||||||
|
}
|
||||||
|
|
||||||
|
const href = resolveApiPath(downloadPath);
|
||||||
const entry = {
|
const entry = {
|
||||||
url: data.url,
|
url: href,
|
||||||
contentType: data.content_type || null,
|
contentType: docResponse.data?.document?.current_version?.version?.content_type || null,
|
||||||
filename: data.filename,
|
filename: docResponse.data?.document?.filename || 'document',
|
||||||
expiresAt: Date.now() + ttl,
|
expiresAt: Date.now() + 5 * 60 * 1000,
|
||||||
};
|
};
|
||||||
setPreviewEntries((prev) => {
|
setPreviewEntries((prev) => {
|
||||||
const next = new Map(prev);
|
const next = new Map(prev);
|
||||||
@@ -3132,7 +3137,7 @@ const AppLayout = () => {
|
|||||||
previewInflightRef.current.set(documentId, request);
|
previewInflightRef.current.set(documentId, request);
|
||||||
return request;
|
return request;
|
||||||
},
|
},
|
||||||
[previewEntries, notifyApiError],
|
[previewEntries, notifyApiError, resolveApiPath],
|
||||||
);
|
);
|
||||||
|
|
||||||
const extractFilesFromDataTransfer = useCallback(async (dataTransfer) => {
|
const extractFilesFromDataTransfer = useCallback(async (dataTransfer) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user