165 lines
5.8 KiB
Python
165 lines
5.8 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
from urllib.parse import urlparse
|
|
|
|
from fastapi.testclient import TestClient
|
|
|
|
|
|
def test_build_public_download_url_uses_dashboard_download_public_url(_isolate_hermes_home):
|
|
from hermes_constants import get_hermes_home
|
|
from hermes_cli.managed_downloads import build_public_download_url
|
|
|
|
home = get_hermes_home()
|
|
(home / "config.yaml").write_text(
|
|
"dashboard:\n"
|
|
" public_url: https://hermesadmin.bremen.com.tw\n"
|
|
" download_public_url: https://hermesadmin.bremen.com.tw\n",
|
|
encoding="utf-8",
|
|
)
|
|
source = home / "demo.txt"
|
|
source.write_text("hello managed download", encoding="utf-8")
|
|
|
|
url = build_public_download_url(str(source))
|
|
|
|
assert url.startswith("https://hermesadmin.bremen.com.tw/downloads/s-")
|
|
|
|
|
|
def test_download_route_serves_staged_file(_isolate_hermes_home):
|
|
from hermes_constants import get_hermes_home
|
|
from hermes_cli.managed_downloads import create_signed_download_token, stage_public_download
|
|
from hermes_cli.web_server import app
|
|
|
|
home = get_hermes_home()
|
|
(home / "config.yaml").write_text(
|
|
"dashboard:\n"
|
|
" public_url: https://hermesadmin.bremen.com.tw\n"
|
|
" download_public_url: https://hermesadmin.bremen.com.tw\n",
|
|
encoding="utf-8",
|
|
)
|
|
source = home / "簡報結果.pdf"
|
|
payload = b"%PDF-1.4 managed-download-test"
|
|
source.write_bytes(payload)
|
|
|
|
staged = stage_public_download(str(source))
|
|
assert staged is not None
|
|
token = create_signed_download_token(str(staged))
|
|
|
|
client = TestClient(app)
|
|
response = client.get(f"/downloads/{token}")
|
|
|
|
assert response.status_code == 200
|
|
assert response.content == payload
|
|
assert "attachment;" in response.headers.get("content-disposition", "").lower()
|
|
assert ".pdf" in response.headers.get("content-disposition", "")
|
|
|
|
|
|
def test_short_download_route_serves_staged_file(_isolate_hermes_home):
|
|
from hermes_constants import get_hermes_home
|
|
from hermes_cli.managed_downloads import build_public_download_url
|
|
from hermes_cli.web_server import app
|
|
|
|
home = get_hermes_home()
|
|
(home / "config.yaml").write_text(
|
|
"dashboard:\n"
|
|
" public_url: https://hermesadmin.bremen.com.tw\n"
|
|
" download_public_url: https://hermesadmin.bremen.com.tw\n",
|
|
encoding="utf-8",
|
|
)
|
|
source = home / "簡報結果-short.pdf"
|
|
payload = b"%PDF-1.4 short-managed-download-test"
|
|
source.write_bytes(payload)
|
|
|
|
url = build_public_download_url(str(source))
|
|
short_id = Path(urlparse(url).path).name
|
|
|
|
client = TestClient(app)
|
|
response = client.get(f"/downloads/{short_id}")
|
|
|
|
assert response.status_code == 200
|
|
assert response.content == payload
|
|
assert "attachment;" in response.headers.get("content-disposition", "").lower()
|
|
assert ".pdf" in response.headers.get("content-disposition", "")
|
|
|
|
|
|
def test_short_download_browser_route_shows_launch_page(_isolate_hermes_home):
|
|
from hermes_constants import get_hermes_home
|
|
from hermes_cli.managed_downloads import build_public_download_url
|
|
from hermes_cli.web_server import app
|
|
|
|
home = get_hermes_home()
|
|
(home / "config.yaml").write_text(
|
|
"dashboard:\n"
|
|
" public_url: https://hermesadmin.bremen.com.tw\n"
|
|
" download_public_url: https://hermesadmin.bremen.com.tw\n",
|
|
encoding="utf-8",
|
|
)
|
|
source = home / "簡報結果-browser.pdf"
|
|
source.write_bytes(b"%PDF-1.4 browser-managed-download-test")
|
|
|
|
url = build_public_download_url(str(source))
|
|
short_id = Path(urlparse(url).path).name
|
|
|
|
client = TestClient(app)
|
|
response = client.get(f"/downloads/{short_id}", headers={"accept": "text/html"})
|
|
|
|
assert response.status_code == 200
|
|
assert "text/html" in response.headers.get("content-type", "")
|
|
assert "下載已開始" in response.text
|
|
assert f'/downloads/s/{short_id.removeprefix("s-")}' in response.text
|
|
|
|
|
|
def test_owner_bound_short_download_rejects_other_scope(_isolate_hermes_home, monkeypatch):
|
|
from hermes_constants import get_hermes_home
|
|
from hermes_cli.managed_downloads import build_public_download_url
|
|
from hermes_cli import web_server
|
|
from hermes_cli.web_server import app
|
|
|
|
home = get_hermes_home()
|
|
(home / "config.yaml").write_text(
|
|
"dashboard:\n"
|
|
" public_url: https://hermesadmin.bremen.com.tw\n"
|
|
" download_public_url: https://hermesadmin.bremen.com.tw\n",
|
|
encoding="utf-8",
|
|
)
|
|
source = home / "owner-bound.pdf"
|
|
source.write_bytes(b"%PDF-1.4 owner-bound")
|
|
|
|
url = build_public_download_url(
|
|
str(source),
|
|
owner_metadata={"email": "owner@bremen.com.tw", "principal_id": "p-123"},
|
|
)
|
|
short_id = Path(urlparse(url).path).name
|
|
monkeypatch.setattr(
|
|
web_server,
|
|
"_dashboard_identity_scope",
|
|
lambda request: {"admin": False, "email": "other@bremen.com.tw", "principal_ids": ["p-999"], "external_user_ids": [], "platforms": []},
|
|
)
|
|
|
|
client = TestClient(app)
|
|
response = client.get(f"/downloads/{short_id}")
|
|
|
|
assert response.status_code == 403
|
|
assert "沒有權限" in response.text
|
|
|
|
|
|
def test_owner_metadata_roundtrips_in_short_download_record(_isolate_hermes_home):
|
|
from hermes_constants import get_hermes_home
|
|
from hermes_cli.managed_downloads import create_short_download_id, resolve_short_download_record
|
|
|
|
home = get_hermes_home()
|
|
source = home / "owner-meta.txt"
|
|
source.write_text("hello", encoding="utf-8")
|
|
|
|
short_id = create_short_download_id(
|
|
str(source),
|
|
owner_metadata={"email": "owner@bremen.com.tw", "principal_id": "p-123", "external_user_id": "openwebui-42", "ignored": "x"},
|
|
)
|
|
record = resolve_short_download_record(short_id)
|
|
|
|
assert record["metadata"] == {
|
|
"email": "owner@bremen.com.tw",
|
|
"principal_id": "p-123",
|
|
"external_user_id": "openwebui-42",
|
|
}
|