# retoor import time import pytest import requests from devplacepy.database import get_table, refresh_snapshot, set_setting from devplacepy.schemas import AdminUserOut from tests.conftest import BASE_URL JSON = {"Accept": "application/json"} _counter = [0] def _unique(prefix="mod"): _counter[0] += 1 return f"{prefix}{int(time.time() * 1000)}{_counter[0]}" def _member(prefix="mod"): name = _unique(prefix) 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, ) return session, name def _admin_session(app_server): session = requests.Session() session.post( f"{BASE_URL}/auth/login", data={"email": "alice@test.devplace", "password": "secret123"}, allow_redirects=True, ) return session def _post(session, content="A post that will be reported by another member."): response = session.post( f"{BASE_URL}/posts/create", data={"title": "Queue subject", "content": content}, headers=JSON, ) assert response.status_code == 200, response.text return response.json()["data"]["uid"] def _report(target_uid, reason="harassment"): reporter, name = _member("rep") response = reporter.post( f"{BASE_URL}/reports/post/{target_uid}", data={"reason": reason, "detail": "Queue test"}, headers=JSON, ) assert response.status_code == 200, response.text refresh_snapshot() row = get_table("content_reports").find_one( target_uid=target_uid, deleted_at=None, order_by=["-created_at"] ) return row["uid"], reporter, name @pytest.fixture(scope="module") def admin(app_server, seeded_db): set_setting("moderation_sla_hours", "24") return _admin_session(app_server) def test_queue_is_admin_only(admin, app_server): member, _ = _member() assert member.get(f"{BASE_URL}/admin/moderation", headers=JSON).status_code == 403 assert requests.get(f"{BASE_URL}/admin/moderation", headers=JSON).status_code == 401 assert admin.get(f"{BASE_URL}/admin/moderation", headers=JSON).status_code == 200 def test_queue_reports_the_sla_snapshot(admin): payload = admin.get(f"{BASE_URL}/admin/moderation", headers=JSON).json() assert payload["sla"]["sla_hours"] == 24 assert "oldest_open_hours" in payload["sla"] assert set(payload["counts"]) == {"open", "acknowledged", "actioned", "dismissed"} def test_queue_is_ordered_oldest_open_first(admin): author, _ = _member("auth") first = _report(_post(author))[0] second = _report(_post(author))[0] payload = admin.get(f"{BASE_URL}/admin/moderation?status=open", headers=JSON).json() order = [entry["uid"] for entry in payload["reports"]] assert order.index(first) < order.index(second) def test_the_report_detail_projects_the_subject_through_the_admin_user_model(admin): author, author_name = _member("subj") report_uid = _report(_post(author))[0] payload = admin.get( f"{BASE_URL}/admin/moderation/{report_uid}", headers=JSON ).json() subject = payload["subject"] assert subject["username"] == author_name assert "password_hash" not in subject assert "api_key" not in subject assert set(subject) <= set(AdminUserOut.model_fields) def test_acknowledging_keeps_the_report_open_for_a_decision(admin): author, _ = _member("auth") report_uid = _report(_post(author))[0] response = admin.post( f"{BASE_URL}/admin/moderation/{report_uid}/status", data={"status": "acknowledged"}, headers=JSON, ) assert response.status_code == 200 refresh_snapshot() assert ( get_table("content_reports").find_one(uid=report_uid)["status"] == "acknowledged" ) def test_a_decision_records_an_action_row_and_resolves_the_report(admin): author, _ = _member("auth") post_uid = _post(author) report_uid, _, _ = _report(post_uid) response = admin.post( f"{BASE_URL}/admin/moderation/{report_uid}/decide", data={"action": "remove_content", "reason": "Breaks the guidelines"}, headers=JSON, ) assert response.status_code == 200, response.text refresh_snapshot() report = get_table("content_reports").find_one(uid=report_uid) assert report["status"] == "actioned" assert report["resolved_at"] action = get_table("moderation_actions").find_one(report_uid=report_uid) assert action["action"] == "remove_content" assert action["reason"] == "Breaks the guidelines" assert get_table("posts").find_one(uid=post_uid)["deleted_at"] def test_deciding_a_resolved_report_twice_is_refused(admin): author, _ = _member("auth") report_uid = _report(_post(author))[0] first = admin.post( f"{BASE_URL}/admin/moderation/{report_uid}/decide", data={"action": "dismiss"}, headers=JSON, ) assert first.status_code == 200 second = admin.post( f"{BASE_URL}/admin/moderation/{report_uid}/decide", data={"action": "dismiss"}, headers=JSON, ) assert second.status_code == 409 def test_escalating_raises_severity_and_keeps_the_report_open(admin): author, _ = _member("auth") report_uid = _report(_post(author), reason="spam")[0] response = admin.post( f"{BASE_URL}/admin/moderation/{report_uid}/decide", data={"action": "escalate"}, headers=JSON, ) assert response.status_code == 200 refresh_snapshot() report = get_table("content_reports").find_one(uid=report_uid) assert report["severity"] == "critical" assert report["status"] == "acknowledged" def test_suspension_blocks_writing_but_not_reading_or_deleting(admin): author, author_name = _member("susp") refresh_snapshot() subject = get_table("users").find_one(username=author_name) response = admin.post( f"{BASE_URL}/admin/users/{subject['uid']}/suspend", data={"reason": "Testing enforcement", "duration_hours": "24"}, headers=JSON, ) assert response.status_code == 200, response.text try: blocked = author.post( f"{BASE_URL}/posts/create", data={"title": "nope", "content": "This must not be published at all."}, headers=JSON, ) assert blocked.status_code == 403 assert author.get(f"{BASE_URL}/feed", headers=JSON).status_code == 200 assert ( author.get(f"{BASE_URL}/profile/{author_name}/delete", headers=JSON).status_code == 200 ) finally: admin.post(f"{BASE_URL}/admin/users/{subject['uid']}/lift", headers=JSON) allowed = author.post( f"{BASE_URL}/posts/create", data={"title": "back", "content": "Writing works again after the lift."}, headers=JSON, ) assert allowed.status_code == 200 def test_ban_revokes_every_session(admin): victim, victim_name = _member("ban") refresh_snapshot() subject = get_table("users").find_one(username=victim_name) response = admin.post( f"{BASE_URL}/admin/users/{subject['uid']}/ban", data={"reason": "Testing the ban path"}, headers=JSON, ) assert response.status_code == 200 refresh_snapshot() assert get_table("users").find_one(uid=subject["uid"])["is_active"] in (0, False) assert victim.get(f"{BASE_URL}/reports/mine", headers=JSON).status_code == 401 def test_an_admin_cannot_enforce_against_themselves(admin, seeded_db): refresh_snapshot() alice = get_table("users").find_one(username="alice_test") response = admin.post( f"{BASE_URL}/admin/users/{alice['uid']}/suspend", data={"reason": "self", "duration_hours": "1"}, headers=JSON, ) assert response.status_code == 200 refresh_snapshot() assert not (get_table("users").find_one(uid=alice["uid"])["suspended_until"] or "")