130 lines
4.1 KiB
Python
130 lines
4.1 KiB
Python
from pathlib import Path
|
|
|
|
from argon2 import PasswordHasher
|
|
from fastapi.testclient import TestClient
|
|
|
|
from app import main
|
|
from app.auth import COOKIE_NAME
|
|
from app.config import Settings, UserSeed
|
|
from app.curator import Curator
|
|
from app.db import Database
|
|
|
|
|
|
WRITE_HEADERS = {"X-Note-Client": "xuxiang-web"}
|
|
|
|
|
|
def test_login_isolation_roles_and_debug_privacy(
|
|
tmp_path: Path, monkeypatch
|
|
):
|
|
hasher = PasswordHasher()
|
|
admin_key = "key-admin-test"
|
|
member_key = "key-member-test"
|
|
users = (
|
|
UserSeed(
|
|
id="admin",
|
|
label="管理员",
|
|
role="admin",
|
|
access_key_hash=hasher.hash(admin_key),
|
|
),
|
|
UserSeed(
|
|
id="member",
|
|
label="用户二",
|
|
role="member",
|
|
access_key_hash=hasher.hash(member_key),
|
|
),
|
|
)
|
|
settings = Settings(
|
|
data_dir=tmp_path,
|
|
database_path=tmp_path / "api.sqlite3",
|
|
users=users,
|
|
session_secret="session-secret-for-tests",
|
|
deepseek_api_key=None,
|
|
deepseek_base_url="https://api.deepseek.com",
|
|
deepseek_model="deepseek-v4-pro",
|
|
cookie_secure=False,
|
|
auth_disabled=False,
|
|
)
|
|
database = Database(settings.database_path)
|
|
monkeypatch.setattr(main, "settings", settings)
|
|
monkeypatch.setattr(main, "db", database)
|
|
monkeypatch.setattr(main, "curator", Curator(database, settings))
|
|
|
|
with TestClient(main.app) as client:
|
|
assert client.post(
|
|
"/api/login", json={"access_key": "wrong"}
|
|
).status_code == 401
|
|
|
|
admin_login = client.post(
|
|
"/api/login", json={"access_key": admin_key}
|
|
)
|
|
assert admin_login.status_code == 200
|
|
assert admin_login.json()["user"]["role"] == "admin"
|
|
admin_cookie = client.cookies.get(COOKIE_NAME)
|
|
|
|
member_login = client.post(
|
|
"/api/login", json={"access_key": member_key}
|
|
)
|
|
assert member_login.status_code == 200
|
|
member_cookie = client.cookies.get(COOKIE_NAME)
|
|
|
|
client.cookies.set(COOKIE_NAME, admin_cookie)
|
|
admin_fragment = client.post(
|
|
"/api/fragments",
|
|
json={"content": "管理员的记录"},
|
|
headers=WRITE_HEADERS,
|
|
)
|
|
assert admin_fragment.status_code == 201
|
|
|
|
client.cookies.set(COOKIE_NAME, member_cookie)
|
|
member_fragment = client.post(
|
|
"/api/fragments",
|
|
json={"content": "用户二的记录"},
|
|
headers=WRITE_HEADERS,
|
|
)
|
|
assert member_fragment.status_code == 201
|
|
assert [item["content"] for item in client.get("/api/fragments").json()["items"]] == [
|
|
"用户二的记录"
|
|
]
|
|
assert client.get("/api/admin/overview").status_code == 403
|
|
|
|
run_id = database.start_agent_run(
|
|
"member",
|
|
member_fragment.json()["id"],
|
|
"deepseek-v4-pro",
|
|
"prompt.v1",
|
|
"high",
|
|
)
|
|
database.add_agent_event(
|
|
run_id,
|
|
"member",
|
|
"decision_committed",
|
|
{
|
|
"standalone": False,
|
|
"assessments": [{"title": "私密产物", "maturity": 42}],
|
|
},
|
|
)
|
|
|
|
client.cookies.set(COOKIE_NAME, admin_cookie)
|
|
assert [item["content"] for item in client.get("/api/fragments").json()["items"]] == [
|
|
"管理员的记录"
|
|
]
|
|
redacted = client.get(f"/api/admin/runs/{run_id}").json()
|
|
assert redacted["fragment"]["content_visible"] is False
|
|
assert redacted["events"][-1]["payload"] == {
|
|
"standalone": False,
|
|
"assessment_count": 1,
|
|
}
|
|
|
|
client.cookies.set(COOKIE_NAME, member_cookie)
|
|
shared = client.patch(
|
|
"/api/account/debug-sharing",
|
|
json={"enabled": True},
|
|
headers=WRITE_HEADERS,
|
|
)
|
|
assert shared.status_code == 200
|
|
|
|
client.cookies.set(COOKIE_NAME, admin_cookie)
|
|
visible = client.get(f"/api/admin/runs/{run_id}").json()
|
|
assert visible["fragment"]["content_visible"] is True
|
|
assert visible["fragment"]["content"] == "用户二的记录"
|