diff --git a/src/db/documents.rs b/src/db/documents.rs index f906493..de6cd74 100644 --- a/src/db/documents.rs +++ b/src/db/documents.rs @@ -1067,4 +1067,59 @@ impl Database { Ok(facets) } + + pub async fn get_document_by_id(&self, document_id: Uuid, user_id: Uuid, user_role: crate::models::UserRole) -> Result> { + let query = if user_role == crate::models::UserRole::Admin { + // Admins can see any document + r#" + SELECT id, filename, original_filename, file_path, file_size, mime_type, content, ocr_text, ocr_confidence, ocr_word_count, ocr_processing_time_ms, ocr_status, ocr_error, ocr_completed_at, tags, created_at, updated_at, user_id + FROM documents + WHERE id = $1 + "# + } else { + // Regular users can only see their own documents + r#" + SELECT id, filename, original_filename, file_path, file_size, mime_type, content, ocr_text, ocr_confidence, ocr_word_count, ocr_processing_time_ms, ocr_status, ocr_error, ocr_completed_at, tags, created_at, updated_at, user_id + FROM documents + WHERE id = $1 AND user_id = $2 + "# + }; + + let row = if user_role == crate::models::UserRole::Admin { + sqlx::query(query) + .bind(document_id) + .fetch_optional(&self.pool) + .await? + } else { + sqlx::query(query) + .bind(document_id) + .bind(user_id) + .fetch_optional(&self.pool) + .await? + }; + + match row { + Some(row) => Ok(Some(Document { + id: row.get("id"), + filename: row.get("filename"), + original_filename: row.get("original_filename"), + file_path: row.get("file_path"), + file_size: row.get("file_size"), + mime_type: row.get("mime_type"), + content: row.get("content"), + ocr_text: row.get("ocr_text"), + ocr_confidence: row.get("ocr_confidence"), + ocr_word_count: row.get("ocr_word_count"), + ocr_processing_time_ms: row.get("ocr_processing_time_ms"), + ocr_status: row.get("ocr_status"), + ocr_error: row.get("ocr_error"), + ocr_completed_at: row.get("ocr_completed_at"), + tags: row.get("tags"), + created_at: row.get("created_at"), + updated_at: row.get("updated_at"), + user_id: row.get("user_id"), + })), + None => Ok(None), + } + } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index a13cf5d..a01c076 100644 --- a/src/main.rs +++ b/src/main.rs @@ -283,7 +283,7 @@ async fn main() -> Result<(), Box> { .nest("/api/webdav", readur::routes::webdav::router()) .merge(readur::swagger::create_swagger_router()) .fallback_service( - ServeDir::new("dist") + ServeDir::new("frontend/dist") .precompressed_gzip() .precompressed_br() .fallback(ServeFile::new("dist/index.html")) @@ -295,7 +295,7 @@ async fn main() -> Result<(), Box> { let current_dir = std::env::current_dir().unwrap_or_else(|_| std::path::PathBuf::from(".")); info!("Server working directory: {}", current_dir.display()); - let dist_path = current_dir.join("dist"); + let dist_path = current_dir.join("frontend/dist"); info!("Looking for static files at: {}", dist_path.display()); info!("dist directory exists: {}", dist_path.exists()); diff --git a/src/routes/documents.rs b/src/routes/documents.rs index 98ccfd9..4e26d96 100644 --- a/src/routes/documents.rs +++ b/src/routes/documents.rs @@ -60,17 +60,12 @@ async fn get_document_by_id( auth_user: AuthUser, Path(document_id): Path, ) -> Result, StatusCode> { - // Get documents for user with proper role-based access - let documents = state + // Get specific document with proper role-based access + let document = state .db - .get_documents_by_user_with_role(auth_user.user.id, auth_user.user.role, 1000, 0) + .get_document_by_id(document_id, auth_user.user.id, auth_user.user.role) .await - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; - - // Find the specific document - let document = documents - .into_iter() - .find(|doc| doc.id == document_id) + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? .ok_or(StatusCode::NOT_FOUND)?; // Convert to DocumentResponse @@ -301,15 +296,11 @@ async fn download_document( auth_user: AuthUser, Path(document_id): Path, ) -> Result, StatusCode> { - let documents = state + let document = state .db - .get_documents_by_user_with_role(auth_user.user.id, auth_user.user.role, 1000, 0) + .get_document_by_id(document_id, auth_user.user.id, auth_user.user.role) .await - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; - - let document = documents - .into_iter() - .find(|doc| doc.id == document_id) + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? .ok_or(StatusCode::NOT_FOUND)?; let file_service = FileService::new(state.config.upload_path.clone()); @@ -342,15 +333,11 @@ async fn view_document( auth_user: AuthUser, Path(document_id): Path, ) -> Result { - let documents = state + let document = state .db - .get_documents_by_user_with_role(auth_user.user.id, auth_user.user.role, 1000, 0) + .get_document_by_id(document_id, auth_user.user.id, auth_user.user.role) .await - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; - - let document = documents - .into_iter() - .find(|doc| doc.id == document_id) + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? .ok_or(StatusCode::NOT_FOUND)?; let file_service = FileService::new(state.config.upload_path.clone()); @@ -394,15 +381,11 @@ async fn get_document_thumbnail( auth_user: AuthUser, Path(document_id): Path, ) -> Result { - let documents = state + let document = state .db - .get_documents_by_user_with_role(auth_user.user.id, auth_user.user.role, 1000, 0) + .get_document_by_id(document_id, auth_user.user.id, auth_user.user.role) .await - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; - - let document = documents - .into_iter() - .find(|doc| doc.id == document_id) + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? .ok_or(StatusCode::NOT_FOUND)?; let file_service = FileService::new(state.config.upload_path.clone()); @@ -447,15 +430,11 @@ async fn get_document_ocr( auth_user: AuthUser, Path(document_id): Path, ) -> Result, StatusCode> { - let documents = state + let document = state .db - .get_documents_by_user_with_role(auth_user.user.id, auth_user.user.role, 1000, 0) + .get_document_by_id(document_id, auth_user.user.id, auth_user.user.role) .await - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; - - let document = documents - .into_iter() - .find(|doc| doc.id == document_id) + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? .ok_or(StatusCode::NOT_FOUND)?; // Return OCR text and metadata @@ -495,15 +474,11 @@ async fn get_processed_image( Path(document_id): Path, ) -> Result { // Check if document exists and belongs to user - let documents = state + let _document = state .db - .get_documents_by_user_with_role(auth_user.user.id, auth_user.user.role, 1000, 0) + .get_document_by_id(document_id, auth_user.user.id, auth_user.user.role) .await - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; - - let _document = documents - .into_iter() - .find(|doc| doc.id == document_id) + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? .ok_or(StatusCode::NOT_FOUND)?; // Get processed image record @@ -553,15 +528,11 @@ async fn retry_ocr( Path(document_id): Path, ) -> Result, StatusCode> { // Check if document exists and belongs to user - let documents = state + let document = state .db - .get_documents_by_user_with_role(auth_user.user.id, auth_user.user.role, 1000, 0) + .get_document_by_id(document_id, auth_user.user.id, auth_user.user.role) .await - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; - - let document = documents - .into_iter() - .find(|doc| doc.id == document_id) + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? .ok_or(StatusCode::NOT_FOUND)?; // Check if document is eligible for OCR retry (failed or not processed)