from __future__ import annotations import io import os import time import uuid import requests BASE_URL = "https://saas.xiaoxiajianji.com/api/v1" PASSWORD = os.environ.get("SMOKE_TEST_PASSWORD", "changeme") def _json_or_raise(name: str, response: requests.Response) -> dict: print(f"{name}={response.status_code}") if response.status_code >= 400: print(response.text[:500]) response.raise_for_status() return response.json() if response.content else {} def _register_login(session: requests.Session, label: str) -> dict: suffix = uuid.uuid4().hex[:10] email = f"smoke-boundary-{label}-{suffix}@example.com" username = f"smoke_boundary_{label}_{suffix}" _json_or_raise( f"{label}_register", session.post( f"{BASE_URL}/auth/register", json={"email": email, "username": username, "password": PASSWORD, "full_name": "Boundary Smoke"}, timeout=30, ), ) login = _json_or_raise( f"{label}_login", session.post(f"{BASE_URL}/auth/login", json={"email": email, "password": PASSWORD}, timeout=30), ) return {"Authorization": f"Bearer {login['access_token']}"} def main() -> None: owner = requests.Session() intruder = requests.Session() owner_headers = _register_login(owner, "owner") intruder_headers = _register_login(intruder, "intruder") _json_or_raise( "owner_workspace", owner.post(f"{BASE_URL}/workspaces", json={"name": "Boundary Workspace"}, headers=owner_headers, timeout=30), ) project = _json_or_raise( "owner_project", owner.post( f"{BASE_URL}/projects", headers=owner_headers, timeout=30, ), ) project_id = project["id"] library = _json_or_raise( "owner_library", owner.post( f"{BASE_URL}/asset-libraries", headers=owner_headers, timeout=30, ), ) library_id = library["id"] upload = _json_or_raise( "owner_upload", owner.post( f"{BASE_URL}/upload", files={"file": ("boundary.mp4", io.BytesIO(b"boundary-owner"), "video/mp4")}, headers=owner_headers, timeout=60, ), ) ingest_id = upload.get("ingest_job_id") for index in range(5): if not ingest_id: break ingest = owner.get(f"{BASE_URL}/ingest-jobs/{ingest_id}", headers=owner_headers, timeout=30) print(f"owner_ingest_{index}={ingest.status_code}") if ingest.status_code == 200 and ingest.json().get("result_asset_id"): break time.sleep(1) task = _json_or_raise( "owner_generation_create", owner.post( f"{BASE_URL}/generation/tasks", headers=owner_headers, timeout=30, ), ) task_id = task["id"] video_id = "" for index in range(8): task_response = owner.get(f"{BASE_URL}/generation/tasks/{task_id}", headers=owner_headers, timeout=30) print(f"owner_generation_{index}={task_response.status_code}") results_response = owner.get( f"{BASE_URL}/generation/tasks/{task_id}/results", headers=owner_headers, timeout=30 ) print(f"owner_generation_results_{index}={results_response.status_code}") if results_response.status_code == 200: items = results_response.json().get("items", []) if items: video_id = items[0]["id"] break time.sleep(2) checks = [ ("anon_me", requests.get(f"{BASE_URL}/auth/me", timeout=30).status_code, {401, 403}), ("anon_workspaces", requests.get(f"{BASE_URL}/workspaces", timeout=30).status_code, {401, 403}), ( "anon_project_get", requests.get(f"{BASE_URL}/projects/{project_id}", timeout=30).status_code, {401, 403, 404}, ), ( "intruder_project_get", intruder.get(f"{BASE_URL}/projects/{project_id}", headers=intruder_headers, timeout=30).status_code, {403, 404}, ), ( "intruder_library_get", intruder.get(f"{BASE_URL}/asset-libraries/{library_id}", headers=intruder_headers, timeout=30).status_code, {403, 404}, ), ( "anon_assets", requests.get(f"{BASE_URL}/assets", params={"library_id": library_id}, timeout=30).status_code, {401, 403, 404}, ), ( "intruder_assets", intruder.get( f"{BASE_URL}/assets", params={"library_id": library_id}, headers=intruder_headers, timeout=30 ).status_code, {403, 404}, ), ( "anon_generation_task", requests.get(f"{BASE_URL}/generation/tasks/{task_id}", timeout=30).status_code, {401, 403, 404}, ), ( "intruder_generation_task", intruder.get(f"{BASE_URL}/generation/tasks/{task_id}", headers=intruder_headers, timeout=30).status_code, {403, 404}, ), ( "intruder_generation_results", intruder.get( f"{BASE_URL}/generation/tasks/{task_id}/results", headers=intruder_headers, timeout=30 ).status_code, {403, 404}, ), ] if video_id: checks.extend( [ ( "intruder_video_get", intruder.get( f"{BASE_URL}/generated-videos/{video_id}", headers=intruder_headers, timeout=30 ).status_code, {403, 404}, ), ( "intruder_video_download", intruder.get( f"{BASE_URL}/generated-videos/{video_id}/download-url", headers=intruder_headers, timeout=30 ).status_code, {403, 404}, ), ] ) upload_response = intruder.post( f"{BASE_URL}/upload", files={"file": ("boundary.txt", io.BytesIO(b"boundary"), "text/plain")}, headers=intruder_headers, timeout=60, ) checks.append(("intruder_upload", upload_response.status_code, {403, 404})) failed = [] for name, status_code, expected in checks: print(f"{name}={status_code}") if status_code not in expected: failed.append(f"{name} expected {sorted(expected)} got {status_code}") if failed: raise RuntimeError("; ".join(failed)) print("public_boundary_flow=ok") if __name__ == "__main__": main()