|
# retoor <retoor@molodetz.nl>
|
|
|
|
import time
|
|
|
|
import requests
|
|
|
|
from devplacepy.database import (
|
|
CONSENT_KINDS,
|
|
consent_granted,
|
|
get_table,
|
|
refresh_snapshot,
|
|
)
|
|
from tests.conftest import BASE_URL
|
|
|
|
JSON = {"Accept": "application/json"}
|
|
_counter = [0]
|
|
|
|
|
|
def _unique(prefix="cons"):
|
|
_counter[0] += 1
|
|
return f"{prefix}{int(time.time() * 1000)}{_counter[0]}"
|
|
|
|
|
|
def _member():
|
|
name = _unique()
|
|
session = requests.Session()
|
|
session.post(
|
|
f"{BASE_URL}/auth/signup",
|
|
data={
|
|
"username": name,
|
|
"email": f"{name}@t.dev",
|
|
"password": "secret123",
|
|
"confirm_password": "secret123",
|
|
"birth_date": "1990-01-01",
|
|
"accept_terms": "1",
|
|
},
|
|
allow_redirects=True,
|
|
)
|
|
refresh_snapshot()
|
|
return session, name, get_table("users").find_one(username=name)
|
|
|
|
|
|
def test_the_privacy_tab_lists_every_consent(app_server):
|
|
session, name, _ = _member()
|
|
payload = session.get(
|
|
f"{BASE_URL}/profile/{name}?tab=privacy", headers=JSON
|
|
).json()
|
|
kinds = {entry["kind"] for entry in payload["consents"]}
|
|
assert set(CONSENT_KINDS) == kinds
|
|
states = {entry["kind"]: entry["state"] for entry in payload["consents"]}
|
|
assert states["ai_third_party"] == "withdrawn"
|
|
assert states["terms"] == "granted"
|
|
|
|
|
|
def test_granting_and_withdrawing_takes_effect_immediately(app_server):
|
|
session, name, user = _member()
|
|
granted = session.post(
|
|
f"{BASE_URL}/profile/{name}/consent",
|
|
data={"kind": "ai_third_party", "granted": "1"},
|
|
headers=JSON,
|
|
)
|
|
assert granted.status_code == 200
|
|
refresh_snapshot()
|
|
assert consent_granted("user", user["uid"], "ai_third_party") is True
|
|
|
|
withdrawn = session.post(
|
|
f"{BASE_URL}/profile/{name}/consent",
|
|
data={"kind": "ai_third_party", "granted": "0"},
|
|
headers=JSON,
|
|
)
|
|
assert withdrawn.status_code == 200
|
|
refresh_snapshot()
|
|
assert consent_granted("user", user["uid"], "ai_third_party") is False
|
|
|
|
|
|
def test_consent_history_is_never_rewritten(app_server):
|
|
session, name, user = _member()
|
|
for granted in ("1", "0", "1"):
|
|
session.post(
|
|
f"{BASE_URL}/profile/{name}/consent",
|
|
data={"kind": "ai_third_party", "granted": granted},
|
|
headers=JSON,
|
|
)
|
|
refresh_snapshot()
|
|
rows = list(
|
|
get_table("user_consents").find(
|
|
owner_kind="user", owner_id=user["uid"], kind="ai_third_party"
|
|
)
|
|
)
|
|
assert len(rows) == 3
|
|
|
|
|
|
def test_an_unknown_consent_kind_is_refused(app_server):
|
|
session, name, _ = _member()
|
|
response = session.post(
|
|
f"{BASE_URL}/profile/{name}/consent",
|
|
data={"kind": "not_a_consent", "granted": "1"},
|
|
headers=JSON,
|
|
)
|
|
assert response.status_code == 422
|
|
|
|
|
|
def test_the_gateway_refuses_user_content_without_consent(app_server):
|
|
session, name, user = _member()
|
|
refresh_snapshot()
|
|
api_key = get_table("users").find_one(uid=user["uid"])["api_key"]
|
|
headers = {**JSON, "Authorization": f"Bearer {api_key}"}
|
|
body = {"model": "molodetz", "messages": [{"role": "user", "content": "hi"}]}
|
|
|
|
refused = requests.post(
|
|
f"{BASE_URL}/openai/v1/chat/completions", json=body, headers=headers
|
|
)
|
|
assert refused.status_code == 403
|
|
assert "consent" in refused.text.lower()
|
|
|
|
session.post(
|
|
f"{BASE_URL}/profile/{name}/consent",
|
|
data={"kind": "ai_third_party", "granted": "1"},
|
|
headers=JSON,
|
|
)
|
|
allowed = requests.post(
|
|
f"{BASE_URL}/openai/v1/chat/completions", json=body, headers=headers
|
|
)
|
|
assert allowed.status_code != 403
|
|
|
|
|
|
def _admin():
|
|
session = requests.Session()
|
|
session.post(
|
|
f"{BASE_URL}/auth/login",
|
|
data={"email": "alice@test.devplace", "password": "secret123"},
|
|
allow_redirects=True,
|
|
)
|
|
return session
|
|
|
|
|
|
def test_an_admin_cannot_grant_a_consent_for_someone_else(app_server, seeded_db):
|
|
_, name, user = _member()
|
|
response = _admin().post(
|
|
f"{BASE_URL}/profile/{name}/consent",
|
|
data={"kind": "ai_third_party", "granted": "1"},
|
|
headers=JSON,
|
|
)
|
|
assert response.status_code == 403
|
|
assert "account holder" in response.text
|
|
refresh_snapshot()
|
|
assert consent_granted("user", user["uid"], "ai_third_party") is False
|
|
|
|
|
|
def test_an_admin_cannot_withdraw_a_consent_for_someone_else(app_server, seeded_db):
|
|
session, name, user = _member()
|
|
session.post(
|
|
f"{BASE_URL}/profile/{name}/consent",
|
|
data={"kind": "ai_third_party", "granted": "1"},
|
|
headers=JSON,
|
|
)
|
|
response = _admin().post(
|
|
f"{BASE_URL}/profile/{name}/consent",
|
|
data={"kind": "ai_third_party", "granted": "0"},
|
|
headers=JSON,
|
|
)
|
|
assert response.status_code == 403
|
|
refresh_snapshot()
|
|
assert consent_granted("user", user["uid"], "ai_third_party") is True
|
|
|
|
|
|
def test_an_admin_cannot_change_someone_elses_mature_preference(app_server, seeded_db):
|
|
_, name, user = _member()
|
|
before = get_table("users").find_one(uid=user["uid"])["mature_opt_in"]
|
|
response = _admin().post(
|
|
f"{BASE_URL}/profile/{name}/mature-content",
|
|
data={"mature_opt_in": "1"},
|
|
headers=JSON,
|
|
)
|
|
assert response.status_code == 403
|
|
assert "account holder" in response.text
|
|
refresh_snapshot()
|
|
assert get_table("users").find_one(uid=user["uid"])["mature_opt_in"] == before
|
|
|
|
|
|
def test_a_stranger_cannot_change_another_members_consent(app_server):
|
|
_, name, user = _member()
|
|
stranger, _, _ = _member()
|
|
response = stranger.post(
|
|
f"{BASE_URL}/profile/{name}/consent",
|
|
data={"kind": "ai_third_party", "granted": "1"},
|
|
headers=JSON,
|
|
)
|
|
assert response.status_code == 403
|
|
refresh_snapshot()
|
|
assert consent_granted("user", user["uid"], "ai_third_party") is False
|
|
|
|
|
|
def test_the_mature_preference_round_trips(app_server):
|
|
session, name, user = _member()
|
|
response = session.post(
|
|
f"{BASE_URL}/profile/{name}/mature-content",
|
|
data={"mature_opt_in": "1"},
|
|
headers=JSON,
|
|
)
|
|
assert response.status_code == 200
|
|
refresh_snapshot()
|
|
assert get_table("users").find_one(uid=user["uid"])["mature_opt_in"] in (1, True)
|
|
session.post(
|
|
f"{BASE_URL}/profile/{name}/mature-content",
|
|
data={"mature_opt_in": "0"},
|
|
headers=JSON,
|
|
)
|
|
refresh_snapshot()
|
|
assert get_table("users").find_one(uid=user["uid"])["mature_opt_in"] in (0, False)
|