"""Verplichte velden mogen niet leeg blijven, en geheimen horen gemaskeerd. Het formulier zette een sterretje achter een verplicht veld en hield verder niets tegen: je kon een app installeren met een leeg databasewachtwoord of een lege JWT-sleutel. De container start dan niet, of draait met een leeg geheim. """ import json import sys from pathlib import Path import pytest sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "server-up")) from conftest import login def _maak_bron(env, naam="testapp", items=None, groepen=None): """Zet een app-sjabloon neer waar _find_stack_src het verwacht.""" from core import git wortel = git.cache_dir("server-up") / "apps" / naam (wortel / "files").mkdir(parents=True, exist_ok=True) variabelen = groepen or [{"title": "Algemeen", "items": items or []}] (wortel / "template.json").write_text(json.dumps({ "kind": "compose", "metadata": {"name": naam, "description": "test"}, "variables": variabelen, }), encoding="utf-8") (wortel / "files" / "compose.yaml").write_text( "services:\n" " << service_name >>:\n" " image: nginx\n" " environment:\n" " - DB_PASSWORD=<< db_password >>\n", encoding="utf-8") return wortel VELDEN = [ {"name": "service_name", "type": "str", "title": "Naam", "default": "testapp", "required": True}, {"name": "db_password", "type": "str", "title": "Databasewachtwoord", "default": "", "required": True}, ] def test_leeg_verplicht_veld_wordt_geweigerd(client, env): csrf = login(client) _maak_bron(env, items=VELDEN) r = client.post("/api/store/install", json={"stack": "testapp", "repo_id": "server-up", "instance": "t1", "values": {"db_password": ""}}, headers={"X-CSRF-Token": csrf}) assert r.status_code == 400, r.get_json() d = r.get_json() assert "Databasewachtwoord" in d["msg"] assert "Databasewachtwoord" in d["missing"] def test_ontbrekend_veld_wordt_geweigerd(client, env): """Niet meegestuurd is net zo fout als leeg meegestuurd.""" csrf = login(client) _maak_bron(env, items=VELDEN) r = client.post("/api/store/install", json={"stack": "testapp", "repo_id": "server-up", "instance": "t2", "values": {}}, headers={"X-CSRF-Token": csrf}) assert r.status_code == 400 assert "Databasewachtwoord" in r.get_json()["missing"] def test_alleen_spaties_telt_als_leeg(client, env): csrf = login(client) _maak_bron(env, items=VELDEN) r = client.post("/api/store/install", json={"stack": "testapp", "repo_id": "server-up", "instance": "t3", "values": {"db_password": " "}}, headers={"X-CSRF-Token": csrf}) assert r.status_code == 400 def test_ingevuld_veld_gaat_door(client, env): csrf = login(client) _maak_bron(env, items=VELDEN) r = client.post("/api/store/install", json={"stack": "testapp", "repo_id": "server-up", "instance": "t4", "values": {"db_password": "geheim123"}}, headers={"X-CSRF-Token": csrf}) assert r.status_code == 200, r.get_json() assert r.get_json().get("job_id") def test_veld_met_een_default_hoeft_niet_meegestuurd(client, env): """service_name heeft een standaardwaarde; die telt als ingevuld.""" csrf = login(client) _maak_bron(env, items=VELDEN) r = client.post("/api/store/install", json={"stack": "testapp", "repo_id": "server-up", "instance": "t5", "values": {"db_password": "x"}}, headers={"X-CSRF-Token": csrf}) assert r.status_code == 200, r.get_json() def test_veld_in_uitgeschakelde_groep_telt_niet_mee(client, env): """Staat de groepsschakelaar uit, dan komt het veld niet in compose terecht en mag het dus leeg blijven.""" csrf = login(client) _maak_bron(env, groepen=[ {"title": "Algemeen", "items": [VELDEN[0]]}, {"title": "Database", "toggle": "gebruik_db", "toggle_default": False, "items": [{"name": "db_password", "type": "str", "title": "Wachtwoord", "default": "", "required": True}]}, ]) r = client.post("/api/store/install", json={"stack": "testapp", "repo_id": "server-up", "instance": "t6", "values": {"gebruik_db": False, "db_password": ""}}, headers={"X-CSRF-Token": csrf}) assert r.status_code == 200, r.get_json() def test_veld_in_ingeschakelde_groep_telt_wel_mee(client, env): csrf = login(client) _maak_bron(env, groepen=[ {"title": "Algemeen", "items": [VELDEN[0]]}, {"title": "Database", "toggle": "gebruik_db", "toggle_default": True, "items": [{"name": "db_password", "type": "str", "title": "Wachtwoord", "default": "", "required": True}]}, ]) r = client.post("/api/store/install", json={"stack": "testapp", "repo_id": "server-up", "instance": "t7", "values": {"gebruik_db": True, "db_password": ""}}, headers={"X-CSRF-Token": csrf}) assert r.status_code == 400 assert "Wachtwoord" in r.get_json()["missing"] # ── Geheimen herkennen ─────────────────────────────────────────────────────── @pytest.mark.parametrize("naam", [ "db_password", "admin_password", "jwt_secret", "secret_key", "api_key", "app_key", "encryption_key", "admin_token", "hass_token", ]) def test_geheime_velden_worden_herkend(env, naam): """Zonder deze markering toonde de interface het wachtwoord als gewone tekst én verscheen de dobbelsteenknop niet, terwijl de beschrijving van zeventien apps ernaar verwijst.""" from core import boilerplates wortel = _maak_bron(env, items=[ {"name": naam, "type": "str", "title": "X", "default": "", "required": True}]) veld = boilerplates.fields(wortel)[0] assert veld["secret"] is True @pytest.mark.parametrize("naam", ["service_name", "port", "appdata_dir", "timezone"]) def test_gewone_velden_zijn_geen_geheim(env, naam): from core import boilerplates wortel = _maak_bron(env, items=[ {"name": naam, "type": "str", "title": "X", "default": "x"}]) assert boilerplates.fields(wortel)[0]["secret"] is False