aps-agent/tests/golden/test_anonymous_visitor_isol...

95 lines
3.5 KiB
Python
Raw Normal View History

# ============================================================
# 免登录云部署:每个浏览器访客只看到自己的项目/会话/个人世界
# ============================================================
from __future__ import annotations
import pytest
from fastapi.testclient import TestClient
@pytest.fixture()
def open_app(tmp_path, monkeypatch):
monkeypatch.setenv("APS_DB_PATH", str(tmp_path / "open.db"))
monkeypatch.setenv("APS_WORLD_PATH", str(tmp_path / "world.json"))
monkeypatch.setenv("APS_AUTH_ENABLED", "0")
from server.db.database import reset_engine
from server.state import store as world_store
world_store._stores.clear()
reset_engine()
from server.gateway.app import create_app
app = create_app()
yield app
reset_engine()
world_store._stores.clear()
def _client(app, visitor: str) -> TestClient:
client = TestClient(app)
client.headers["X-APS-Visitor-ID"] = visitor
return client
def test_anonymous_visitors_get_distinct_identities(open_app):
alpha = _client(open_app, "visitor-alpha-0001")
bravo = _client(open_app, "visitor-bravo-0002")
user_a = alpha.get("/api/auth/me").json()["user"]
user_b = bravo.get("/api/auth/me").json()["user"]
assert user_a["auth_kind"] == "anonymous"
assert user_a["user_id"] != user_b["user_id"]
def test_anonymous_visitors_only_see_own_projects_and_sessions(open_app):
alpha = _client(open_app, "visitor-alpha-0001")
bravo = _client(open_app, "visitor-bravo-0002")
assert alpha.post(
"/api/projects", json={"id": "proj_anon_a", "name": "访客 A 项目"},
).status_code == 200
alpha_workspace = alpha.get("/api/workspace").json()
assert [row["id"] for row in alpha_workspace["projects"]] == ["proj_anon_a"]
bravo_workspace = bravo.get("/api/workspace").json()
assert bravo_workspace["projects"] == []
assert bravo.get("/api/projects/proj_anon_a/members").status_code == 404
bravo_session = next(row for row in bravo_workspace["sessions"] if row["scope"] == "personal")
assert bravo.get(f"/api/sessions/{bravo_session['id']}/messages").status_code == 200
alpha_personal = next(
row for row in alpha_workspace["sessions"] if row["scope"] == "personal"
)
assert alpha_personal["id"] != bravo_session["id"]
assert bravo.get(f"/api/sessions/{alpha_personal['id']}/messages").status_code == 404
def test_same_visitor_reuses_own_workspace(open_app):
first = _client(open_app, "visitor-same-0001")
first.post("/api/projects", json={"id": "proj_anon_same", "name": "同一访客项目"})
cookie = first.cookies.get("aps_anonymous_id")
assert cookie
second = TestClient(open_app)
second.cookies.set("aps_anonymous_id", cookie)
workspace = second.get("/api/workspace").json()
assert [row["id"] for row in workspace["projects"]] == ["proj_anon_same"]
def test_anonymous_cookie_survives_localstorage_reset(open_app):
first = _client(open_app, "visitor-ls-reset-0001")
first.post("/api/projects", json={"id": "proj_anon_cookie", "name": "Cookie 项目"})
cookie = first.cookies.get("aps_anonymous_id")
assert cookie
# 模拟 localStorage 被清空:新浏览器上下文没有访客头,只有服务端 Cookie。
second = TestClient(open_app)
second.cookies.set("aps_anonymous_id", cookie)
second.headers["X-APS-Visitor-ID"] = "visitor-recreated-0001"
workspace = second.get("/api/workspace").json()
assert [row["id"] for row in workspace["projects"]] == ["proj_anon_cookie"]