Let only admins change the global settings

BINDERY_ADMIN_USERS lists the admins of the cwa and proxy modes. Only an
admin can change the global settings and the global rules, and read or
change personal.ini. Without a list, each user is an admin.
This commit is contained in:
tim
2026-10-02 23:37:33 +02:00
parent 751b52da77
commit bb6c87cdd5
11 changed files with 140 additions and 8 deletions
+45
View File
@@ -71,6 +71,7 @@ def test_cwa_login(client, cwa):
"authenticated": False,
"mode": "cwa",
"user": None,
"admin": False,
"logout_url": None,
}
assert login(client, password="wrong").status_code == 401
@@ -170,10 +171,54 @@ def test_proxy_header(client, monkeypatch):
"authenticated": True,
"mode": "proxy",
"user": "alice",
"admin": True,
"logout_url": "https://auth.example.com/logout",
}
@pytest.mark.parametrize(("user", "admin"), [("alice", True), ("Alice", True), ("bob", False)])
def test_only_an_admin_changes_the_global_settings(client, monkeypatch, tmp_path, user, admin):
monkeypatch.setattr(config, "PERSONAL_INI", tmp_path / "personal.ini")
monkeypatch.setattr(config, "AUTH_METHOD", "proxy")
monkeypatch.setattr(config, "ADMIN_USERS", ["alice"])
sid = orchestrator.store.create_story("https://www.royalroad.com/fiction/1", "www.royalroad.com", "S", "W", [])
headers = {**H, "X-Remote-User": user}
status = 200 if admin else 403
assert client.get("/api/auth/check", headers=headers).json["admin"] is admin
assert ("personal_ini" in client.get("/api/settings", headers=headers).json) is admin
for data in ({"recent_chapters": 5}, {"personal_ini": "[defaults]\n"}):
assert client.put("/api/settings", json=data, headers=headers).status_code == status
assert (orchestrator.get_settings()["recent_chapters"] == 5) is admin
assert config.PERSONAL_INI.exists() is admin
rules = {"rules": [{"pattern": "a", "replacement": "b"}]}
response = client.put("/api/rules", json=rules, headers=headers)
assert response.status_code == status
assert bool(orchestrator.store.rules(None)) is admin
if not admin:
assert response.json == {"error": "Only an admin can do this. BINDERY_ADMIN_USERS lists the admins."}
# Each user can read the global rules, and change the rules and the settings of a story.
assert client.get("/api/rules", headers=headers).status_code == 200
assert client.put(f"/api/stories/{sid}/rules", json=rules, headers=headers).status_code == 200
assert client.put(f"/api/stories/{sid}/settings", json={"recheck_days": 3}, headers=headers).status_code == 200
def test_the_api_key_and_single_user_modes_are_admins(client, monkeypatch):
monkeypatch.setattr(config, "ADMIN_USERS", ["alice"])
assert client.get("/api/auth/check").json["admin"] # the none mode has no users
monkeypatch.setattr(config, "AUTH_METHOD", "proxy")
monkeypatch.setattr(config, "API_KEY", "secret")
key = {"X-Api-Key": "secret"}
assert client.get("/api/auth/check", headers=key).json["admin"]
assert client.put("/api/settings", json={"recent_chapters": 2}, headers=key).status_code == 200
assert auth.is_admin(auth.Identity("bob", "proxy")) is False
monkeypatch.setattr(config, "AUTH_METHOD", "local")
assert auth.is_admin(auth.Identity("bob", "session"))
# Without a list, each user is an admin.
monkeypatch.setattr(config, "AUTH_METHOD", "proxy")
monkeypatch.setattr(config, "ADMIN_USERS", [])
assert auth.is_admin(auth.Identity("bob", "proxy"))
@pytest.mark.parametrize(
("trusted", "address", "accepted"),
[