Files
BadNote/server/badnote_server/routers/v1_vault_router.py

64 lines
2.0 KiB
Python
Raw Normal View History

"""v1 vault sync-assist API — vault files are the source of truth."""
from __future__ import annotations
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status
from fastapi.responses import Response
from ..auth import get_current_user
from .. import vault_store
router = APIRouter()
@router.get("/manifest")
async def get_manifest(user_id: str = Depends(get_current_user)) -> dict:
"""List all files in the user's vault with size/mtime/sha256."""
return vault_store.build_manifest(user_id)
@router.get("/files/{file_path:path}")
async def download_file(
file_path: str,
user_id: str = Depends(get_current_user),
) -> Response:
try:
data = vault_store.read_file(user_id, file_path)
except ValueError as exc:
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc
except FileNotFoundError:
raise HTTPException(status.HTTP_404_NOT_FOUND, detail="file not found")
return Response(
content=data,
media_type="application/octet-stream",
headers={"X-Vault-Path": file_path},
)
@router.put("/files/{file_path:path}")
async def upload_file(
file_path: str,
upload: UploadFile = File(...),
user_id: str = Depends(get_current_user),
) -> dict:
try:
data = await upload.read()
entry = vault_store.write_file(user_id, file_path, data)
except ValueError as exc:
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc
return entry.to_dict()
@router.delete("/files/{file_path:path}")
async def remove_file(
file_path: str,
user_id: str = Depends(get_current_user),
) -> dict:
try:
vault_store.delete_file(user_id, file_path, tombstone=True)
except ValueError as exc:
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc
except FileNotFoundError:
raise HTTPException(status.HTTP_404_NOT_FOUND, detail="file not found")
return {"deleted": file_path, "tombstone": True}