refactor(09-05): CODE-09 purge — Phase 8 backend sub-packages (WHAT comments removed)
- api/admin/users.py: removed module docstring + 7 WHAT function docstrings - api/admin/quotas.py: removed module docstring + 2 WHAT function docstrings - api/admin/ai.py: removed module docstring + 3 WHAT inline comments; security invariant docstrings preserved - api/admin/shared.py: unchanged (all comments are WHY — constraint notes) - api/documents/upload.py: removed 4 WHAT inline comments; T-03-05/T-03-06 WHY notes preserved - api/documents/content.py: removed WHAT function docstring + WHAT inline comment - api/documents/crud.py: removed 7 WHAT inline comments; D-16 + security constraint docstrings preserved - api/auth/shared.py: removed module docstring + 1 WHAT inline comment - api/auth/tokens.py: removed module docstring + 8 WHAT function docstrings/comments; family-revocation + SEC-02 WHY notes preserved - api/auth/totp.py: removed module docstring + 2 WHAT function docstrings + 2 WHAT inline comments - api/auth/password.py: removed module docstring + 2 WHAT function docstrings + 3 WHAT inline comments - All NO-prefix anchor comments and security-invariant WHY comments preserved - pytest: 413 passed, 1 failed (pre-existing ModuleNotFoundError unrelated to purge)
This commit is contained in:
@@ -62,19 +62,6 @@ async def stream_document_content(
|
||||
session: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_regular_user),
|
||||
):
|
||||
"""Stream document bytes directly from MinIO (DOC-02).
|
||||
|
||||
T-04-05-01: uses get_regular_user — admin role → 403 (critical security invariant).
|
||||
T-04-05-02: bytes fetched via get_object() ONLY — presigned_get_url() never called.
|
||||
T-04-05-03: Range header validated via _parse_range(); invalid range → 416.
|
||||
T-04-05-04: access gated on ownership OR active Share.recipient_id.
|
||||
|
||||
Returns 200 (or 206 for Range requests) with:
|
||||
Content-Type: doc.content_type
|
||||
Content-Disposition: inline; filename="<filename>"
|
||||
Accept-Ranges: bytes
|
||||
Content-Length: <size>
|
||||
"""
|
||||
request.state.current_user = current_user
|
||||
try:
|
||||
uid = uuid.UUID(doc_id)
|
||||
@@ -97,9 +84,6 @@ async def stream_document_content(
|
||||
if share is None:
|
||||
raise HTTPException(status_code=404, detail="Document not found")
|
||||
|
||||
# Fetch bytes from the correct backend — get_storage_backend_for_document handles
|
||||
# all backends (MinIO, Google Drive, OneDrive, Nextcloud, WebDAV) transparently
|
||||
# (D-15, T-04-05-02). NEVER via presigned URL for cloud backends (D-14).
|
||||
try:
|
||||
import api.documents as _doc_pkg # late import allows test monkeypatching via api.documents
|
||||
storage_backend = await _doc_pkg.get_storage_backend_for_document(doc, current_user, session)
|
||||
|
||||
@@ -99,12 +99,10 @@ async def list_documents(
|
||||
items.append(d)
|
||||
return {"items": items, "total": total, "page": page, "per_page": per_page}
|
||||
|
||||
# New path: direct ORM query with sort/filter/FTS
|
||||
from db.models import DocumentTopic, Topic # noqa: PLC0415 (avoid circular at module top)
|
||||
|
||||
stmt = select(Document).where(Document.user_id == current_user.id)
|
||||
|
||||
# Topic filter (join-based, same as list_metadata)
|
||||
if topic is not None:
|
||||
stmt = (
|
||||
stmt.join(DocumentTopic, DocumentTopic.document_id == Document.id)
|
||||
@@ -112,7 +110,6 @@ async def list_documents(
|
||||
.where(Topic.name == topic)
|
||||
)
|
||||
|
||||
# Folder filter
|
||||
if folder_id is not None:
|
||||
try:
|
||||
folder_uuid = uuid.UUID(folder_id)
|
||||
@@ -120,7 +117,6 @@ async def list_documents(
|
||||
raise HTTPException(status_code=404, detail="Folder not found")
|
||||
stmt = stmt.where(Document.folder_id == folder_uuid)
|
||||
|
||||
# Sort
|
||||
sort_col = Document.created_at # default: date
|
||||
if sort == "name":
|
||||
sort_col = Document.filename
|
||||
@@ -147,13 +143,11 @@ async def list_documents(
|
||||
result = await session.execute(stmt)
|
||||
docs_orm = result.scalars().all()
|
||||
|
||||
# is_shared subquery
|
||||
shared_result = await session.execute(
|
||||
select(Share.document_id).where(Share.owner_id == current_user.id)
|
||||
)
|
||||
shared_ids = {row[0] for row in shared_result.fetchall()}
|
||||
|
||||
# Serialize
|
||||
all_items = []
|
||||
for doc in docs_orm:
|
||||
from services.storage import _doc_to_dict, _load_topic_names # noqa: PLC0415
|
||||
@@ -199,7 +193,6 @@ async def get_document(
|
||||
|
||||
is_recipient = False
|
||||
if doc.user_id != current_user.id:
|
||||
# Allow recipients of an active share to view the document
|
||||
share_result = await session.execute(
|
||||
select(Share).where(
|
||||
Share.document_id == uid,
|
||||
@@ -250,7 +243,6 @@ async def patch_document(
|
||||
if doc is None or doc.user_id != current_user.id:
|
||||
raise HTTPException(404, "Document not found")
|
||||
|
||||
# Require at least one field to be set (model_fields_set tracks provided fields)
|
||||
if not body.model_fields_set:
|
||||
raise HTTPException(422, "At least one field (filename, folder_id) must be provided")
|
||||
|
||||
@@ -311,7 +303,6 @@ async def delete_document(
|
||||
_doc_id = doc.id
|
||||
_ip = get_client_ip(request)
|
||||
|
||||
# Cloud routing: attempt provider delete unless remove_only is set
|
||||
if is_cloud and not remove_only:
|
||||
try:
|
||||
import api.documents as _doc_pkg # late import allows test monkeypatching via api.documents
|
||||
|
||||
@@ -129,7 +129,6 @@ async def upload_document(
|
||||
"""
|
||||
request.state.current_user = current_user
|
||||
if target_backend == "minio":
|
||||
# MinIO: generate a presigned URL for client-side PUT (existing flow reused)
|
||||
doc_id = uuid.uuid4()
|
||||
suffix = Path(file.filename or "file").suffix.lower()
|
||||
object_key = f"{current_user.id}/{doc_id}/{uuid.uuid4()}{suffix}"
|
||||
@@ -152,7 +151,6 @@ async def upload_document(
|
||||
)
|
||||
return {"upload_url": upload_url, "document_id": str(doc_id)}
|
||||
|
||||
# Cloud backend path
|
||||
if target_backend not in _CLOUD_PROVIDERS:
|
||||
raise HTTPException(
|
||||
status_code=422,
|
||||
@@ -174,11 +172,9 @@ async def upload_document(
|
||||
detail=f"No active {target_backend} connection found. Please connect in Settings.",
|
||||
)
|
||||
|
||||
# Decrypt per-user credentials
|
||||
master_key = settings.cloud_creds_key.encode()
|
||||
credentials = decrypt_credentials(master_key, str(current_user.id), conn.credentials_enc)
|
||||
|
||||
# Read file bytes
|
||||
file_bytes = await file.read()
|
||||
filename = file.filename or "upload"
|
||||
content_type = file.content_type or "application/octet-stream"
|
||||
@@ -186,7 +182,6 @@ async def upload_document(
|
||||
|
||||
doc_id = uuid.uuid4()
|
||||
|
||||
# Instantiate backend and upload
|
||||
if target_backend == "google_drive":
|
||||
from storage.google_drive_backend import GoogleDriveBackend # lazy import
|
||||
cloud_backend = GoogleDriveBackend(credentials)
|
||||
@@ -319,13 +314,11 @@ async def confirm_upload(
|
||||
row = result.fetchone()
|
||||
|
||||
if row is None:
|
||||
# Quota exceeded — fetch current quota state for the 413 body
|
||||
quota_result = await session.execute(
|
||||
text("SELECT used_bytes, limit_bytes FROM quotas WHERE user_id = :uid"),
|
||||
{"uid": doc.user_id.hex},
|
||||
)
|
||||
q = quota_result.fetchone()
|
||||
# Delete the pending Document row and best-effort remove the MinIO object
|
||||
await session.delete(doc)
|
||||
try:
|
||||
await get_storage_backend().delete_object(doc.object_key)
|
||||
|
||||
Reference in New Issue
Block a user