forked from retoor/devplacepy
The primary administrator was the earliest Admin by created_at with no further condition, so a soft-deleted or deactivated account could hold the role and then be refused by the api-key path, leaving nobody able to use the database API, the backup download or cross-owner container management. Rows with no recorded signup time also sorted ahead of every real account. Scan the earliest admins instead and take the first that is neither deleted nor deactivated, with missing timestamps sorted last. Also stop the projects listing returning 500 when project_type or description is NULL (the dict default never applies to an existing NULL column), align the issue test fixture with its unit twin so a combined run cannot collide on a fixed uid, read the settings value from the database rather than a stale per-process cache, and give the seeded and fixture admins the is_active and created_at fields that every real signup writes.
103 lines
2.7 KiB
Python
103 lines
2.7 KiB
Python
# retoor <retoor@molodetz.nl>
|
|
|
|
import time
|
|
import pytest
|
|
import requests
|
|
from tests.conftest import BASE_URL
|
|
from devplacepy.database import (
|
|
clear_settings_cache,
|
|
get_setting,
|
|
get_table,
|
|
refresh_snapshot,
|
|
set_setting,
|
|
)
|
|
|
|
JSON = {"Accept": "application/json"}
|
|
_counter_cfg = [0]
|
|
|
|
|
|
@pytest.fixture(scope="module", autouse=True)
|
|
def _settings(app_server):
|
|
set_setting("rate_limit_per_minute", "1000000")
|
|
set_setting("registration_open", "1")
|
|
yield
|
|
|
|
|
|
def _admin(seeded_db):
|
|
refresh_snapshot()
|
|
key = get_table("users").find_one(username="alice_test")["api_key"]
|
|
s = requests.Session()
|
|
s.headers.update({"X-API-KEY": key, **JSON})
|
|
return s
|
|
|
|
|
|
def _member():
|
|
_counter_cfg[0] += 1
|
|
name = f"cfgmem{int(time.time() * 1000)}{_counter_cfg[0]}"
|
|
requests.post(
|
|
f"{BASE_URL}/auth/signup",
|
|
data={
|
|
"username": name,
|
|
"email": f"{name}@t.dev",
|
|
"password": "secret123",
|
|
"confirm_password": "secret123",
|
|
},
|
|
allow_redirects=True,
|
|
)
|
|
refresh_snapshot()
|
|
s = requests.Session()
|
|
s.headers.update(
|
|
{"X-API-KEY": get_table("users").find_one(username=name)["api_key"], **JSON}
|
|
)
|
|
return s
|
|
|
|
|
|
def test_admin_saves_service_config(seeded_db):
|
|
admin = _admin(seeded_db)
|
|
new_model = f"test-model-{int(time.time())}"
|
|
original = get_setting("news_ai_model", "")
|
|
try:
|
|
r = admin.post(
|
|
f"{BASE_URL}/admin/services/news/config",
|
|
data={"news_ai_model": new_model},
|
|
)
|
|
assert r.status_code == 200, r.text[:300]
|
|
assert r.json().get("ok") is True
|
|
refresh_snapshot()
|
|
# the server persisted it in its own process; drop this process's 60s settings
|
|
# cache so the assertion reads the database rather than a pre-save snapshot
|
|
clear_settings_cache()
|
|
assert get_setting("news_ai_model", "") == new_model
|
|
finally:
|
|
if original:
|
|
set_setting("news_ai_model", original)
|
|
|
|
|
|
def test_unknown_service_config_404(seeded_db):
|
|
admin = _admin(seeded_db)
|
|
r = admin.post(
|
|
f"{BASE_URL}/admin/services/no_such_service/config",
|
|
data={"foo": "bar"},
|
|
)
|
|
assert r.status_code == 404
|
|
assert r.json().get("ok") is False
|
|
|
|
|
|
def test_member_cannot_save_config(app_server):
|
|
member = _member()
|
|
r = member.post(
|
|
f"{BASE_URL}/admin/services/news/config",
|
|
data={"news_ai_model": "x"},
|
|
allow_redirects=False,
|
|
)
|
|
assert r.status_code in (302, 303, 403)
|
|
|
|
|
|
def test_guest_cannot_save_config(app_server):
|
|
r = requests.post(
|
|
f"{BASE_URL}/admin/services/news/config",
|
|
data={"news_ai_model": "x"},
|
|
allow_redirects=False,
|
|
)
|
|
assert r.status_code in (302, 303, 401)
|