Stream media through the backend (browser-reachable, privacy-checked)
Presigned URLs point at the internal minio:9000 host a browser can't reach. Add ObjectStore.get_object and a GET /media/{id}/content endpoint that resolves visibility and streams the bytes; MediaRead.url now points there. Keeps the object store private and downloads behind the privacy engine.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Justin Paul <justin@jpaul.me>
This commit is contained in:
@@ -46,6 +46,9 @@ class FakeObjectStore(ObjectStore):
|
||||
async def put_object(self, *, key: str, data: bytes, content_type: str) -> None:
|
||||
self.objects[key] = (data, content_type)
|
||||
|
||||
async def get_object(self, *, key: str) -> bytes:
|
||||
return self.objects[key][0]
|
||||
|
||||
async def presigned_get_url(self, *, key: str) -> str:
|
||||
return f"https://objects.test/{key}"
|
||||
|
||||
|
||||
@@ -22,13 +22,18 @@ async def test_media_upload_list_delete(client):
|
||||
body = resp.json()
|
||||
assert body["original_filename"] == "scan.txt"
|
||||
assert body["byte_size"] == 11
|
||||
assert body["url"].startswith("https://objects.test/")
|
||||
assert body["url"] == f"/api/v1/trees/{tree_id}/media/{body['id']}/content"
|
||||
media_id = body["id"]
|
||||
|
||||
listed = await client.get(f"/api/v1/trees/{tree_id}/media", headers=h)
|
||||
assert listed.status_code == 200
|
||||
assert len(listed.json()) == 1
|
||||
|
||||
# The content endpoint streams the bytes back.
|
||||
content = await client.get(f"/api/v1/trees/{tree_id}/media/{media_id}/content", headers=h)
|
||||
assert content.status_code == 200
|
||||
assert content.content == b"hello world"
|
||||
|
||||
resp = await client.delete(f"/api/v1/trees/{tree_id}/media/{media_id}", headers=h)
|
||||
assert resp.status_code == 204
|
||||
assert len((await client.get(f"/api/v1/trees/{tree_id}/media", headers=h)).json()) == 0
|
||||
|
||||
Reference in New Issue
Block a user