File size: 2,631 Bytes
79860d3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
"""
api/documents.py  —  Document upload / delete endpoints
"""
from fastapi import APIRouter, HTTPException, UploadFile, File
from fastapi.responses import FileResponse
from app.models.api_models import SuccessResponse, DocumentListResponse
from app.services.document_service import document_service
from app.services.profile_service import profile_service
from app.storage.file_storage import ProfileFileStorage

router = APIRouter(prefix="/api/profiles/{slug}/documents", tags=["documents"])


@router.get("", response_model=DocumentListResponse)
def list_documents(slug: str):
    if not profile_service.profile_exists(slug):
        raise HTTPException(404, f"Profile '{slug}' not found")
    return document_service.list_documents(slug)


@router.post("", status_code=201)
async def upload_document(slug: str, file: UploadFile = File(...)):
    if not profile_service.profile_exists(slug):
        raise HTTPException(404, f"Profile '{slug}' not found")
    try:
        data = await file.read()
        doc = document_service.upload_document(slug, file.filename, data)
        return doc
    except ValueError as e:
        raise HTTPException(400, str(e))


@router.get("/{filename}/view")
def view_document(slug: str, filename: str):
    """Serve a document file so the browser can open/preview it natively."""
    if not profile_service.profile_exists(slug):
        raise HTTPException(404, f"Profile '{slug}' not found")
    fs = ProfileFileStorage(slug)
    file_path = fs.docs_dir / filename
    if not file_path.exists():
        raise HTTPException(404, f"Document '{filename}' not found")

    import mimetypes
    media_type, _ = mimetypes.guess_type(filename)
    media_type = media_type or "application/octet-stream"

    ext = filename.rsplit(".", 1)[-1].lower()
    browser_viewable = {"pdf", "txt", "md", "csv"}
    disposition = "inline" if ext in browser_viewable else "attachment"

    # Browsers have no native CSV renderer — serve as plain text so it displays inline
    if ext == "csv":
        media_type = "text/plain; charset=utf-8"

    return FileResponse(
        str(file_path),
        media_type=media_type,
        headers={"Content-Disposition": f'{disposition}; filename="{filename}"'},
    )


@router.delete("/{filename}")
def delete_document(slug: str, filename: str):
    if not profile_service.profile_exists(slug):
        raise HTTPException(404, f"Profile '{slug}' not found")
    ok = document_service.delete_document(slug, filename)
    if not ok:
        raise HTTPException(404, f"Document '{filename}' not found")
    return SuccessResponse(message=f"'{filename}' deleted")